4 * Ullrich von Bassewitz, 20.06.1998
31 /*****************************************************************************/
33 /*****************************************************************************/
37 static void ParseTypeSpec (DeclSpec* D, int Default);
38 /* Parse a type specificier */
42 /*****************************************************************************/
43 /* internal functions */
44 /*****************************************************************************/
48 static void optional_modifiers (void)
49 /* Eat optional "const" or "volatile" tokens */
51 while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
59 static void optionalint (void)
60 /* Eat an optional "int" token */
62 if (curtok == TOK_INT) {
70 static void optionalsigned (void)
71 /* Eat an optional "signed" token */
73 if (curtok == TOK_SIGNED) {
81 static void InitDeclSpec (DeclSpec* D)
82 /* Initialize the DeclSpec struct for use */
91 static void InitDeclaration (Declaration* D)
92 /* Initialize the Declaration struct for use */
101 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
102 /* Parse a storage class */
104 /* Assume we're using an explicit storage class */
105 D->Flags &= ~DS_DEF_STORAGE;
107 /* Check the storage class given */
111 D->StorageClass = SC_EXTERN | SC_STATIC;
116 D->StorageClass = SC_STATIC;
121 D->StorageClass = SC_REGISTER | SC_STATIC;
126 D->StorageClass = SC_AUTO;
131 D->StorageClass = SC_TYPEDEF;
136 /* No storage class given, use default */
137 D->Flags |= DS_DEF_STORAGE;
138 D->StorageClass = DefStorage;
145 static void ParseEnumDecl (void)
146 /* Process an enum declaration . */
151 /* Accept forward definitions */
152 if (curtok != TOK_LCURLY) {
156 /* Skip the opening curly brace */
159 /* Read the enum tags */
161 while (curtok != TOK_RCURLY) {
163 /* We expect an identifier */
164 if (curtok != TOK_IDENT) {
165 Error (ERR_IDENT_EXPECTED);
169 /* Remember the identifier and skip it */
170 strcpy (Ident, CurTok.Ident);
173 /* Check for an assigned value */
174 if (curtok == TOK_ASSIGN) {
178 EnumVal = lval.e_const;
181 /* Add an entry to the symbol table */
182 AddEnumSym (Ident, EnumVal++);
184 /* Check for end of definition */
185 if (curtok != TOK_COMMA)
194 static SymEntry* ParseStructDecl (const char* Name, type StructType)
195 /* Parse a struct/union declaration. */
204 if (curtok != TOK_LCURLY) {
205 /* Just a forward declaration. Try to find a struct with the given
206 * name. If there is none, insert a forward declaration into the
207 * current lexical level.
209 Entry = FindTagSym (Name);
211 Entry = AddStructSym (Name, 0, 0);
212 } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
213 /* Already defined in the level but no struct */
214 Error (ERR_SYMBOL_KIND);
219 /* Add a forward declaration for the struct in the current lexical level */
220 Entry = AddStructSym (Name, 0, 0);
222 /* Skip the curly brace */
225 /* Enter a new lexical level for the struct */
228 /* Parse struct fields */
230 while (curtok != TOK_RCURLY) {
232 /* Get the type of the entry */
234 InitDeclSpec (&Spec);
235 ParseTypeSpec (&Spec, -1);
237 /* Read fields with this type */
240 /* Get type and name of the struct field */
242 ParseDecl (&Spec, &Decl, 0);
244 /* Add a field entry to the table */
245 AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
247 /* Calculate offset of next field/size of the union */
248 Offs = SizeOf (Decl.Type);
249 if (StructType == T_STRUCT) {
257 if (curtok != TOK_COMMA)
264 /* Skip the closing brace */
267 /* Remember the symbol table and leave the struct level */
268 FieldTab = GetSymTab ();
271 /* Make a real entry from the forward decl and return it */
272 return AddStructSym (Name, Size, FieldTab);
277 static void ParseTypeSpec (DeclSpec* D, int Default)
278 /* Parse a type specificier */
284 /* Assume have an explicit type */
285 D->Flags &= ~DS_DEF_TYPE;
287 /* Skip const or volatile modifiers if needed */
288 optional_modifiers ();
290 /* Look at the data type */
301 D->Type[0] = GetDefaultChar();
307 if (curtok == TOK_UNSIGNED) {
310 D->Type[0] = T_ULONG;
322 if (curtok == TOK_UNSIGNED) {
325 D->Type[0] = T_USHORT;
330 D->Type[0] = T_SHORT;
354 D->Type[0] = T_SHORT;
382 D->Type[0] = T_UCHAR;
389 D->Type[0] = T_USHORT;
396 D->Type[0] = T_ULONG;
413 StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
416 if (curtok == TOK_IDENT) {
417 strcpy (Ident, CurTok.Ident);
420 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
422 /* Remember we have an extra type decl */
423 D->Flags |= DS_EXTRA_TYPE;
424 /* Declare the struct in the current scope */
425 Entry = ParseStructDecl (Ident, StructType);
426 /* Encode the struct entry into the type */
427 D->Type[0] = StructType;
428 EncodePtr (D->Type+1, Entry);
429 D->Type[DECODE_SIZE+1] = T_END;
434 if (curtok != TOK_LCURLY) {
436 if (curtok == TOK_IDENT) {
437 /* Find an entry with this name */
438 Entry = FindTagSym (CurTok.Ident);
440 if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
441 Error (ERR_SYMBOL_KIND);
444 /* Insert entry into table ### */
446 /* Skip the identifier */
449 Error (ERR_IDENT_EXPECTED);
452 /* Remember we have an extra type decl */
453 D->Flags |= DS_EXTRA_TYPE;
454 /* Parse the enum decl */
461 Entry = FindSym (CurTok.Ident);
462 if (Entry && IsTypeDef (Entry)) {
465 TypeCpy (D->Type, Entry->Type);
472 Error (ERR_TYPE_EXPECTED);
476 D->Flags |= DS_DEF_TYPE;
477 D->Type[0] = (type) Default;
486 static type* ParamTypeCvt (type* T)
487 /* If T is an array, convert it to a pointer else do nothing. Return the
500 static void ParseOldStyleParamList (FuncDesc* F)
501 /* Parse an old style (K&R) parameter list */
504 while (curtok != TOK_RPAREN) {
506 /* List of identifiers expected */
507 if (curtok != TOK_IDENT) {
508 Error (ERR_IDENT_EXPECTED);
511 /* Create a symbol table entry with type int */
512 AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
514 /* Count arguments */
517 /* Skip the identifier */
520 /* Check for more parameters */
521 if (curtok == TOK_COMMA) {
528 /* Skip right paren. We must explicitly check for one here, since some of
529 * the breaks above bail out without checking.
533 /* An optional list of type specifications follows */
534 while (curtok != TOK_LCURLY) {
538 /* Read the declaration specifier */
539 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
541 /* We accept only auto and register as storage class specifiers, but
542 * we ignore all this, since we use auto anyway.
544 if ((Spec.StorageClass & SC_AUTO) == 0 &&
545 (Spec.StorageClass & SC_REGISTER) == 0) {
546 Error (ERR_ILLEGAL_STORAGE_CLASS);
549 /* Parse a comma separated variable list */
554 /* Read the parameter */
555 ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
556 if (Decl.Ident[0] != '\0') {
558 /* We have a name given. Search for the symbol */
559 SymEntry* Sym = FindLocalSym (Decl.Ident);
561 /* Found it, change the default type to the one given */
562 ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
564 Error (ERR_UNKNOWN_IDENT, Decl.Ident);
568 if (curtok == TOK_COMMA) {
576 /* Variable list must be semicolon terminated */
583 static void ParseAnsiParamList (FuncDesc* F)
584 /* Parse a new style (ANSI) parameter list */
587 while (curtok != TOK_RPAREN) {
593 /* Allow an ellipsis as last parameter */
594 if (curtok == TOK_ELLIPSIS) {
596 F->Flags |= FD_ELLIPSIS;
600 /* Read the declaration specifier */
601 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
603 /* We accept only auto and register as storage class specifiers, but
604 * we ignore all this and use auto.
606 if ((Spec.StorageClass & SC_AUTO) == 0 &&
607 (Spec.StorageClass & SC_REGISTER) == 0) {
608 Error (ERR_ILLEGAL_STORAGE_CLASS);
610 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
612 /* Allow parameters without a name, but remember if we had some to
613 * eventually print an error message later.
615 ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
616 if (Decl.Ident[0] == '\0') {
618 /* Unnamed symbol. Generate a name that is not user accessible,
619 * then handle the symbol normal.
621 AnonName (Decl.Ident, "param");
622 F->Flags |= FD_UNNAMED_PARAMS;
624 /* Clear defined bit on nonames */
625 Spec.StorageClass &= ~SC_DEF;
628 /* Create a symbol table entry */
629 AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
631 /* Count arguments */
634 /* Check for more parameters */
635 if (curtok == TOK_COMMA) {
642 /* Skip right paren. We must explicitly check for one here, since some of
643 * the breaks above bail out without checking.
647 /* Check if this is a function definition */
648 if (curtok == TOK_LCURLY) {
649 /* Print an error if in strict ANSI mode and we have unnamed
652 if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
653 Error (ERR_MISSING_PARAM_NAME);
660 static FuncDesc* ParseFuncDecl (void)
661 /* Parse the argument list of a function. */
666 /* Create a new function descriptor */
667 FuncDesc* F = NewFuncDesc ();
669 /* Enter a new lexical level */
670 EnterFunctionLevel ();
672 /* Check for several special parameter lists */
673 if (curtok == TOK_RPAREN) {
674 /* Parameter list is empty */
675 F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
676 } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
677 /* Parameter list declared as void */
679 F->Flags |= FD_VOID_PARAM;
680 } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
681 /* Old style (K&R) function. Assume variable param list. */
682 F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
686 if ((F->Flags & FD_OLDSTYLE) == 0) {
687 /* New style function */
688 ParseAnsiParamList (F);
690 /* Old style function */
691 ParseOldStyleParamList (F);
694 /* Assign offsets. If the function has a variable parameter list,
695 * there's one additional byte (the arg size).
697 Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
698 Sym = GetSymTab()->SymTail;
700 unsigned Size = SizeOf (Sym->Type);
703 F->ParamSize += Size;
707 /* Leave the lexical level remembering the symbol tables */
708 RememberFunctionLevel (F);
710 /* Return the function descriptor */
716 static void Decl (Declaration* D, unsigned Mode)
717 /* Recursively process declarators. Build a type array in reverse order. */
719 if (curtok == TOK_STAR) {
721 /* Allow optional const or volatile modifiers */
722 optional_modifiers ();
726 } else if (curtok == TOK_LPAREN) {
730 } else if (curtok == TOK_FASTCALL) {
731 /* Remember the current type pointer */
733 /* Skip the fastcall token */
735 /* Parse the function */
737 /* Set the fastcall flag */
739 Error (ERR_ILLEGAL_MODIFIER);
741 FuncDesc* F = DecodePtr (T+1);
742 F->Flags |= FD_FASTCALL;
746 /* Things depend on Mode now:
747 * - Mode == DM_NEED_IDENT means:
748 * we *must* have a type and a variable identifer.
749 * - Mode == DM_NO_IDENT means:
750 * we must have a type but no variable identifer
751 * (if there is one, it's not read).
752 * - Mode == DM_ACCEPT_IDENT means:
753 * we *may* have an identifier. If there is an identifier,
754 * it is read, but it is no error, if there is none.
756 if (Mode == DM_NO_IDENT) {
758 } else if (curtok == TOK_IDENT) {
759 strcpy (D->Ident, CurTok.Ident);
762 if (Mode == DM_NEED_IDENT) {
763 Error (ERR_IDENT_EXPECTED);
770 while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
771 if (curtok == TOK_LPAREN) {
772 /* Function declaration */
775 /* Parse the function declaration */
776 F = ParseFuncDecl ();
781 /* Array declaration */
782 unsigned long Size = 0;
784 /* Read the size if it is given */
785 if (curtok != TOK_RBRACK) {
800 /*****************************************************************************/
802 /*****************************************************************************/
806 type* ParseType (type* Type)
807 /* Parse a complete type specification */
812 /* Get a type without a default */
813 InitDeclSpec (&Spec);
814 ParseTypeSpec (&Spec, -1);
816 /* Parse additional declarators */
817 InitDeclaration (&Decl);
818 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
820 /* Copy the type to the target buffer */
821 TypeCpy (Type, Decl.Type);
823 /* Return a pointer to the target buffer */
829 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
830 /* Parse a variable, type or function declaration */
832 /* Initialize the Declaration struct */
835 /* Get additional declarators and the identifier */
838 /* Add the base type. */
839 TypeCpy (D->T, Spec->Type);
841 /* Check the size of the generated type */
842 if (!IsFunc (D->Type) && SizeOf (D->Type) >= 0x10000) {
843 Error (ERR_ILLEGAL_SIZE);
849 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
850 /* Parse a declaration specification */
852 /* Initialize the DeclSpec struct */
855 /* First, get the storage class specifier for this declaration */
856 ParseStorageClass (D, DefStorage);
858 /* Parse the type specifiers */
859 ParseTypeSpec (D, DefType);
864 void CheckEmptyDecl (const DeclSpec* D)
865 /* Called after an empty type declaration (that is, a type declaration without
866 * a variable). Checks if the declaration does really make sense and issues a
870 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
871 Warning (WARN_USELESS_DECL);
877 static void ParseVoidInit (void)
878 /* Parse an initialization of a void variable (special cc65 extension) */
882 /* Allow an arbitrary list of values */
886 switch (lval.e_tptr[0]) {
890 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
891 /* Make it byte sized */
892 lval.e_const &= 0xFF;
903 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
904 /* Make it word sized */
905 lval.e_const &= 0xFFFF;
916 Error (ERR_ILLEGAL_TYPE);
921 if (curtok != TOK_COMMA) {
926 } while (curtok != TOK_RCURLY);
933 static void ParseStructInit (type* Type)
934 /* Parse initialization of a struct or union */
939 /* Consume the opening curly brace */
942 /* Get a pointer to the struct entry from the type */
943 Entry = (SymEntry*) Decode (Type + 1);
945 /* Check if this struct definition has a field table. If it doesn't, it
946 * is an incomplete definition.
948 Tab = Entry->V.S.SymTab;
950 Error (ERR_INIT_INCOMPLETE_TYPE);
951 /* Returning here will cause lots of errors, but recovery is difficult */
955 /* Get a pointer to the list of symbols */
956 Entry = Tab->SymHead;
957 while (curtok != TOK_RCURLY) {
959 Error (ERR_TOO_MANY_INITIALIZERS);
962 ParseInit (Entry->Type);
963 Entry = Entry->NextSym;
964 if (curtok != TOK_COMMA)
969 /* Consume the closing curly brace */
972 /* If there are struct fields left, reserve additional storage */
974 g_zerobytes (SizeOf (Entry->Type));
975 Entry = Entry->NextSym;
983 void ParseInit (type *tptr)
984 /* Parse initialization of variables */
997 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
998 /* Make it byte sized */
999 lval.e_const &= 0xFF;
1001 assignadjust (tptr, &lval);
1011 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1012 /* Make it word sized */
1013 lval.e_const &= 0xFFFF;
1015 assignadjust (tptr, &lval);
1022 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1023 /* Make it long sized */
1024 lval.e_const &= 0xFFFFFFFF;
1026 assignadjust (tptr, &lval);
1031 sz = Decode (tptr + 1);
1032 t = tptr + DECODE_SIZE + 1;
1033 if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == TOK_SCONST) {
1034 str = GetLiteral (curval);
1035 count = strlen (str) + 1;
1036 TranslateLiteralPool (curval); /* Translate into target charset */
1037 g_defbytes (str, count);
1038 ResetLiteralOffs (curval); /* Remove string from pool */
1043 while (curtok != TOK_RCURLY) {
1044 ParseInit (tptr + DECODE_SIZE + 1);
1046 if (curtok != TOK_COMMA)
1053 Encode (tptr + 1, count);
1054 } else if (count < sz) {
1055 g_zerobytes ((sz - count) * SizeOf (tptr + DECODE_SIZE + 1));
1056 } else if (count > sz) {
1057 Error (ERR_TOO_MANY_INITIALIZERS);
1063 ParseStructInit (tptr);
1068 /* Special cc65 extension in non ANSI mode */
1075 Error (ERR_ILLEGAL_TYPE);