X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fdeclare.c;h=9f0a94a27d9f267b4fadc266d0fdd5222e44a5b8;hb=3f4096d3030095605f28b4cfa73563c53a563df6;hp=025c1046d3f82b97a30c0e3b95d1a3680b3798a1;hpb=f6376d7d60c8894441ee4ea7e0e81f0583f104b4;p=cc65 diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 025c1046d..9f0a94a27 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 1998-2004 Ullrich von Bassewitz */ +/* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -38,12 +38,15 @@ #include /* common */ +#include "addrsize.h" +#include "mmodel.h" #include "xmalloc.h" /* cc65 */ #include "anonname.h" #include "codegen.h" #include "datatype.h" +#include "declare.h" #include "declattr.h" #include "error.h" #include "expr.h" @@ -54,7 +57,7 @@ #include "pragma.h" #include "scanner.h" #include "symtab.h" -#include "declare.h" +#include "typeconv.h" @@ -421,7 +424,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default) optionalsigned (); optionalint (); D->Type[0] = T_SHORT; - D->Type[1] = T_END; + D->Type[1] = T_END; } break; @@ -459,7 +462,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default) NextToken (); /* FALL THROUGH */ - default: + default: D->Type[0] = T_INT; D->Type[1] = T_END; break; @@ -501,6 +504,18 @@ static void ParseTypeSpec (DeclSpec* D, int Default) } break; + case TOK_FLOAT: + NextToken (); + D->Type[0] = T_FLOAT; + D->Type[1] = T_END; + break; + + case TOK_DOUBLE: + NextToken (); + D->Type[0] = T_DOUBLE; + D->Type[1] = T_END; + break; + case TOK_STRUCT: case TOK_UNION: StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION; @@ -806,11 +821,18 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec) ParseOldStyleParamList (F); } + /* Remember the last function parameter. We need it later for several + * purposes, for example when passing stuff to fastcall functions. Since + * more symbols are added to the table, it is easier if we remember it + * now, since it is currently the last entry in the symbol table. + */ + F->LastParam = GetSymTab()->SymTail; + /* Assign offsets. If the function has a variable parameter list, * there's one additional byte (the arg size). */ Offs = (F->Flags & FD_VARIADIC)? 1 : 0; - Sym = GetSymTab()->SymTail; + Sym = F->LastParam; while (Sym) { unsigned Size = CheckedSizeOf (Sym->Type); if (SymIsRegVar (Sym)) { @@ -823,6 +845,13 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec) Sym = Sym->PrevSym; } + /* Add the default address size for the function */ + if (CodeAddrSize == ADDR_SIZE_FAR) { + F->Flags |= FD_FAR; + } else { + F->Flags |= FD_NEAR; + } + /* Leave the lexical level remembering the symbol tables */ RememberFunctionLevel (F); @@ -832,39 +861,114 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec) +static unsigned FunctionModifierFlags (void) +/* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */ +{ + /* Read the flags */ + unsigned Flags = FD_NONE; + while (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) { + + /* Get the flag bit for the next token */ + unsigned F = FD_NONE; + switch (CurTok.Tok) { + case TOK_FASTCALL: F = FD_FASTCALL; break; + case TOK_NEAR: F = FD_NEAR; break; + case TOK_FAR: F = FD_FAR; break; + default: Internal ("Unexpected token: %d", CurTok.Tok); + } + + /* Remember the flag for this modifier */ + if (Flags & F) { + Error ("Duplicate modifier"); + } + Flags |= F; + + /* Skip the token */ + NextToken (); + } + + /* Sanity check */ + if ((Flags & (FD_NEAR | FD_FAR)) == (FD_NEAR | FD_FAR)) { + Error ("Cannot specify both, `__near__' and `__far__' modifiers"); + Flags &= ~(FD_NEAR | FD_FAR); + } + + /* Return the flags read */ + return Flags; +} + + + +static void ApplyFunctionModifiers (type* T, unsigned Flags) +/* Apply a set of function modifier flags to a function */ +{ + /* Get the function descriptor */ + FuncDesc* F = GetFuncDesc (T); + + /* Special check for __fastcall__ */ + if ((Flags & FD_FASTCALL) != 0 && IsVariadicFunc (T)) { + Error ("Cannot apply `__fastcall__' to functions with " + "variable parameter list"); + Flags &= ~FD_FASTCALL; + } + + /* Remove the default function address size modifiers */ + F->Flags &= ~(FD_NEAR | FD_FAR); + + /* Add the new modifers */ + F->Flags |= Flags; +} + + + static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode) /* Recursively process declarators. Build a type array in reverse order. */ { - + /* Pointer to something */ if (CurTok.Tok == TOK_STAR) { - type T = T_PTR; + + type T; + + /* Skip the star */ NextToken (); + /* Allow optional const or volatile qualifiers */ - T |= OptionalQualifiers (T_QUAL_NONE); + T = T_PTR | OptionalQualifiers (T_QUAL_NONE); + + /* Parse the type, the pointer points to */ Decl (Spec, D, Mode); + *D->T++ = T; return; - } else if (CurTok.Tok == TOK_LPAREN) { - NextToken (); - Decl (Spec, D, Mode); - ConsumeRParen (); - } else if (CurTok.Tok == TOK_FASTCALL) { + } + + /* Function modifiers */ + if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) { + /* Remember the current type pointer */ type* T = D->T; - /* Skip the fastcall token */ - NextToken (); + + /* Read the flags */ + unsigned Flags = FunctionModifierFlags (); + /* Parse the function */ Decl (Spec, D, Mode); - /* Set the fastcall flag */ + + /* Check that we have a function */ if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) { - Error ("__fastcall__ modifier applied to non function"); - } else if (IsVariadicFunc (T)) { - Error ("Cannot apply __fastcall__ to functions with variable parameter list"); + Error ("Function modifier applied to non function"); } else { - FuncDesc* F = GetFuncDesc (T); - F->Flags |= FD_FASTCALL; - } + ApplyFunctionModifiers (T, Flags); + } + + /* Done */ return; + } + + if (CurTok.Tok == TOK_LPAREN) { + NextToken (); + Decl (Spec, D, Mode); + ConsumeRParen (); } else { /* Things depend on Mode now: * - Mode == DM_NEED_IDENT means: @@ -944,7 +1048,6 @@ type* ParseType (type* Type) ParseTypeSpec (&Spec, -1); /* Parse additional declarators */ - InitDeclaration (&Decl); ParseDecl (&Spec, &Decl, DM_NO_IDENT); /* Copy the type to the target buffer */ @@ -1066,28 +1169,51 @@ static void ClosingCurlyBraces (unsigned BracesExpected) -static unsigned ParseSimpleInit (type* T) -/* Parse initializaton for simple data types. Return the number of data bytes. */ +static unsigned ParseScalarInit (type* T) +/* Parse initializaton for scalar data types. Return the number of data bytes. */ { - static const unsigned long Masks[] = { - 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL - }; ExprDesc ED; /* Optional opening brace */ unsigned BraceCount = OpeningCurlyBraces (0); - /* Get the size of the expected type */ - unsigned Size = SizeOf (T); - CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0])); + /* We warn if an initializer for a scalar contains braces, because this is + * quite unusual and often a sign for some problem in the input. + */ + if (BraceCount > 0) { + Warning ("Braces around scalar initializer"); + } + + /* Get the expression and convert it to the target type */ + ConstExpr (&ED); + TypeConversion (&ED, 0, T); + + /* Output the data */ + DefineData (&ED); + + /* Close eventually opening braces */ + ClosingCurlyBraces (BraceCount); + + /* Done */ + return SizeOf (T); +} + + + +static unsigned ParsePointerInit (type* T) +/* Parse initializaton for pointer data types. Return the number of data bytes. */ +{ + /* Optional opening brace */ + unsigned BraceCount = OpeningCurlyBraces (0); /* Expression */ + ExprDesc ED; ConstExpr (&ED); if ((ED.Flags & E_MCTYPE) == E_TCONST) { /* Make the const value the correct size */ - ED.ConstVal &= Masks[Size-1]; + ED.ConstVal &= 0xFFFF; } - assignadjust (T, &ED); + TypeConversion (&ED, 0, T); /* Output the data */ DefineData (&ED); @@ -1096,7 +1222,7 @@ static unsigned ParseSimpleInit (type* T) ClosingCurlyBraces (BraceCount); /* Done */ - return Size; + return SIZEOF_PTR; } @@ -1120,6 +1246,18 @@ static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers) /* Translate into target charset */ TranslateLiteralPool (CurTok.IVal); + + /* If the array is one too small for the string literal, omit the + * trailing zero. + */ + if (ElementCount != UNSPECIFIED && + ElementCount != FLEXIBLE && + Count == ElementCount + 1) { + /* Omit the trailing zero */ + --Count; + } + + /* Output the data */ g_defbytes (Str, Count); /* Remove string from pool */ @@ -1319,10 +1457,12 @@ static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers) case T_USHORT: case T_INT: case T_UINT: - case T_PTR: case T_LONG: case T_ULONG: - return ParseSimpleInit (T); + return ParseScalarInit (T); + + case T_PTR: + return ParsePointerInit (T); case T_ARRAY: return ParseArrayInit (T, AllowFlexibleMembers); @@ -1344,13 +1484,25 @@ static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers) } } - + unsigned ParseInit (type* T) /* Parse initialization of variables. Return the number of data bytes. */ { - return ParseInitInternal (T, !ANSI); + /* Parse the initialization */ + unsigned Size = ParseInitInternal (T, !ANSI); + + /* The initialization may not generate code on global level, because code + * outside function scope will never get executed. + */ + if (HaveGlobalCode ()) { + Error ("Non constant initializers"); + RemoveGlobalCode (); + } + + /* Return the size needed for the initialization */ + return Size; }