X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcompile.c;h=3dd7bffa43a8e84aff4a73c8c35567ba52eebdb5;hb=ce931b85be8c41d30510685c6b92fbe74e12aec9;hp=0e751edf9701bf0db4dbffc4a57b0ed4575896b7;hpb=49fd7134e51d012b1c96497978fb7a55afb3b094;p=cc65 diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 0e751edf9..3dd7bffa4 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -2,14 +2,14 @@ /* */ /* compile.c */ /* */ -/* Top level compiler subroutine */ +/* Top level compiler subroutine */ /* */ /* */ /* */ -/* (C) 2000-2002 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -37,6 +37,7 @@ #include /* common */ +#include "debugflag.h" #include "version.h" #include "xmalloc.h" #include "xsprintf.h" @@ -45,18 +46,20 @@ #include "asmlabel.h" #include "asmstmt.h" #include "codegen.h" +#include "compile.h" #include "declare.h" #include "error.h" #include "expr.h" #include "function.h" #include "global.h" -#include "incpath.h" #include "input.h" #include "litpool.h" #include "macrotab.h" +#include "output.h" #include "pragma.h" +#include "preproc.h" +#include "standard.h" #include "symtab.h" -#include "compile.h" @@ -79,9 +82,7 @@ static void Parse (void) /* Parse until end of input */ while (CurTok.Tok != TOK_CEOF) { - DeclSpec Spec; - Declaration Decl; - int NeedStorage; + DeclSpec Spec; /* Check for empty statements */ if (CurTok.Tok == TOK_SEMI) { @@ -106,10 +107,13 @@ static void Parse (void) ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT); /* Don't accept illegal storage classes */ - if (Spec.StorageClass == SC_AUTO || Spec.StorageClass == SC_REGISTER) { - Error ("Illegal storage class"); - Spec.StorageClass = SC_EXTERN | SC_STATIC; - } + if ((Spec.StorageClass & SC_TYPE) == 0) { + if ((Spec.StorageClass & SC_AUTO) != 0 || + (Spec.StorageClass & SC_REGISTER) != 0) { + Error ("Illegal storage class"); + Spec.StorageClass = SC_EXTERN | SC_STATIC; + } + } /* Check if this is only a type declaration */ if (CurTok.Tok == TOK_SEMI) { @@ -118,22 +122,12 @@ static void Parse (void) continue; } - /* Check if we must reserve storage for the variable. We do - * this if we don't had a storage class given ("int i") or - * if the storage class is explicitly specified as static. - * This means that "extern int i" will not get storage - * allocated. - */ - NeedStorage = (Spec.StorageClass & SC_TYPEDEF) == 0 && - ((Spec.Flags & DS_DEF_STORAGE) != 0 || - (Spec.StorageClass & (SC_STATIC | SC_EXTERN)) == SC_STATIC); - /* Read declarations for this type */ Entry = 0; comma = 0; while (1) { - unsigned SymFlags; + Declaration Decl; /* Read the next declaration */ ParseDecl (&Spec, &Decl, DM_NEED_IDENT); @@ -142,22 +136,44 @@ static void Parse (void) break; } - /* Get the symbol flags */ - SymFlags = Spec.StorageClass; - if (IsTypeFunc (Decl.Type)) { - SymFlags |= SC_FUNC; - } else { - if (NeedStorage) { - /* We will allocate storage, variable is defined */ - SymFlags |= SC_STORAGE | SC_DEF; - } + /* Check if we must reserve storage for the variable. We do this, + * if it is not a typedef or function, if we don't had a storage + * class given ("int i") or if the storage class is explicitly + * specified as static. This means that "extern int i" will not + * get storage allocated. + */ + if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && + (Decl.StorageClass & SC_TYPEDEF) != SC_TYPEDEF && + ((Spec.Flags & DS_DEF_STORAGE) != 0 || + (Decl.StorageClass & (SC_STATIC | SC_EXTERN)) == SC_STATIC)) { + + /* We will allocate storage */ + Decl.StorageClass |= SC_STORAGE | SC_DEF; } + /* If this is a function declarator that is not followed by a comma + * or semicolon, it must be followed by a function body. If this is + * the case, convert an empty parameter list into one accepting no + * parameters (same as void) as required by the standard. + */ + if ((Decl.StorageClass & SC_FUNC) != 0 && + (CurTok.Tok != TOK_COMMA) && + (CurTok.Tok != TOK_SEMI)) { + + FuncDesc* D = GetFuncDesc (Decl.Type); + if (D->Flags & FD_EMPTY) { + D->Flags = (D->Flags & ~(FD_EMPTY | FD_VARIADIC)) | FD_VOID_PARAM; + } + } + /* Add an entry to the symbol table */ - Entry = AddGlobalSym (Decl.Ident, Decl.Type, SymFlags); + Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); + + /* Add declaration attributes */ + SymUseAttr (Entry, &Decl); /* Reserve storage for the variable if we need to */ - if (SymFlags & SC_STORAGE) { + if (Decl.StorageClass & SC_STORAGE) { /* Get the size of the variable */ unsigned Size = SizeOf (Decl.Type); @@ -171,18 +187,23 @@ static void Parse (void) if (Size == 0) { if (!IsTypeVoid (Decl.Type)) { if (!IsTypeArray (Decl.Type)) { - /* Size is unknown and not an array */ + /* Size is unknown and not an array */ Error ("Variable `%s' has unknown size", Decl.Ident); } - } else if (ANSI) { + } else if (IS_Get (&Standard) != STD_CC65) { /* We cannot declare variables of type void */ Error ("Illegal type for variable `%s'", Decl.Ident); } } - /* Switch to the data or rodata segment */ - if (IsQualConst (Decl.Type)) { - g_userodata (); + /* Switch to the data or rodata segment. For arrays, check + * the element qualifiers, since not the array but its + * elements are const. + */ + if (IsQualConst (Decl.Type) || + (IsTypeArray (Decl.Type) && + IsQualConst (GetElementType (Decl.Type)))) { + g_userodata (); } else { g_usedata (); } @@ -200,19 +221,27 @@ static void Parse (void) if (IsTypeVoid (Decl.Type)) { /* We cannot declare variables of type void */ Error ("Illegal type for variable `%s'", Decl.Ident); - } else if (Size == 0) { - /* Size is unknown */ - Error ("Variable `%s' has unknown size", Decl.Ident); + Entry->Flags &= ~(SC_STORAGE | SC_DEF); + } else if (Size == 0) { + /* Size is unknown. Is it an array? */ + if (!IsTypeArray (Decl.Type)) { + Error ("Variable `%s' has unknown size", Decl.Ident); + } + Entry->Flags &= ~(SC_STORAGE | SC_DEF); } - /* Switch to the BSS segment */ - g_usebss (); + /* Allocate storage if it is still needed */ + if (Entry->Flags & SC_STORAGE) { - /* Define a label */ - g_defgloblabel (Entry->Name); + /* Switch to the BSS segment */ + g_usebss (); + + /* Define a label */ + g_defgloblabel (Entry->Name); - /* Allocate space for uninitialized variable */ - g_res (SizeOf (Entry->Type)); + /* Allocate space for uninitialized variable */ + g_res (Size); + } } } @@ -231,16 +260,19 @@ static void Parse (void) /* Function */ if (!comma) { - if (CurTok.Tok == TOK_SEMI) { - /* Prototype only */ NextToken (); - } else { - if (Entry) { - NewFunc (Entry); - } + + /* Function body. Check for duplicate function definitions */ + if (SymIsDef (Entry)) { + Error ("Body for function `%s' has already been defined", + Entry->Name); + } + + /* Parse the function body */ + NewFunc (Entry); } } @@ -258,10 +290,8 @@ static void Parse (void) void Compile (const char* FileName) /* Top level compile routine. Will setup things and call the parser. */ { - char* Path; - char Buf[20]; - char DateStr[20]; - char TimeStr[20]; + char DateStr[32]; + char TimeStr[32]; time_t Time; struct tm* TM; @@ -273,50 +303,46 @@ void Compile (const char* FileName) "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - /* Add some standard paths to the include search path */ - AddIncludePath ("", INC_USER); /* Current directory */ - AddIncludePath ("include", INC_SYS); -#ifdef CC65_INC - AddIncludePath (CC65_INC, INC_SYS); -#else - AddIncludePath ("/usr/lib/cc65/include", INC_SYS); -#endif - Path = getenv ("CC65_INC"); - if (Path) { - AddIncludePath (Path, INC_SYS | INC_USER); - } - /* Add macros that are always defined */ - DefineNumericMacro ("__CC65__", (VER_MAJOR * 0x100) + (VER_MINOR * 0x10) + VER_PATCH); + DefineNumericMacro ("__CC65__", GetVersionAsNumber ()); - /* Strict ANSI macro */ - if (ANSI) { - DefineNumericMacro ("__STRICT_ANSI__", 1); - } + /* Language standard that is supported */ + DefineNumericMacro ("__CC65_STD_C89__", STD_C89); + DefineNumericMacro ("__CC65_STD_C99__", STD_C99); + DefineNumericMacro ("__CC65_STD_CC65__", STD_CC65); + DefineNumericMacro ("__CC65_STD__", IS_Get (&Standard)); - /* Optimization macros */ - if (Optimize) { - DefineNumericMacro ("__OPT__", 1); - if (FavourSize == 0) { - DefineNumericMacro ("__OPT_i__", 1); - } - if (EnableRegVars) { - DefineNumericMacro ("__OPT_r__", 1); - } - if (InlineStdFuncs) { - DefineNumericMacro ("__OPT_s__", 1); - } + /* Optimization macros. Since no source code has been parsed for now, the + * IS_Get functions access the values in effect now, regardless of any + * changes using #pragma later. + */ + if (IS_Get (&Optimize)) { + long CodeSize = IS_Get (&CodeSizeFactor); + DefineNumericMacro ("__OPT__", 1); + if (CodeSize > 100) { + DefineNumericMacro ("__OPT_i__", CodeSize); + } + if (IS_Get (&EnableRegVars)) { + DefineNumericMacro ("__OPT_r__", 1); + } + if (IS_Get (&InlineStdFuncs)) { + DefineNumericMacro ("__OPT_s__", 1); + } } /* __TIME__ and __DATE__ macros */ Time = time (0); TM = localtime (&Time); - strftime (Buf, sizeof (Buf), "%e %Y", TM); - xsprintf (DateStr, sizeof (DateStr), "\"%s %s\"", MonthNames[TM->tm_mon], Buf); + xsprintf (DateStr, sizeof (DateStr), "\"%s %2d %d\"", + MonthNames[TM->tm_mon], TM->tm_mday, TM->tm_year + 1900); strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM); DefineTextMacro ("__DATE__", DateStr); DefineTextMacro ("__TIME__", TimeStr); + /* Other standard macros */ + /* DefineNumericMacro ("__STDC__", 1); <- not now */ + DefineNumericMacro ("__STDC_HOSTED__", 1); + /* Initialize the literal pool */ InitLiteralPool (); @@ -329,18 +355,41 @@ void Compile (const char* FileName) /* Open the input file */ OpenMainFile (FileName); - /* Ok, start the ball rolling... */ - Parse (); + /* Are we supposed to compile or just preprocess the input? */ + if (PreprocessOnly) { - /* Dump the literal pool. */ - DumpLiteralPool (); + /* Open the file */ + OpenOutputFile (); - /* Write imported/exported symbols */ - EmitExternals (); + /* Preprocess each line and write it to the output file */ + while (NextLine ()) { + Preprocess (); + WriteOutput ("%.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); + } + + /* Close the output file */ + CloseOutputFile (); + + if (Debug) { + PrintMacroStats (stdout); + } + + } else { + + /* Ok, start the ball rolling... */ + Parse (); + + /* Dump the literal pool. */ + DumpLiteralPool (); + + /* Write imported/exported symbols */ + EmitExternals (); + + if (Debug) { + PrintLiteralPoolStats (stdout); + PrintMacroStats (stdout); + } - if (Debug) { - PrintLiteralPoolStats (stdout); - PrintMacroStats (stdout); } /* Leave the main lexical level */ @@ -352,3 +401,4 @@ void Compile (const char* FileName) +