/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2004 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdlib.h>
+#include <time.h>
-#include "../common/version.h"
+/* common */
+#include "debugflag.h"
+#include "version.h"
+#include "xmalloc.h"
+#include "xsprintf.h"
+/* cc65 */
#include "asmlabel.h"
+#include "asmstmt.h"
#include "codegen.h"
#include "declare.h"
#include "error.h"
#include "expr.h"
#include "function.h"
#include "global.h"
-#include "incpath.h"
-#include "io.h"
+#include "input.h"
#include "litpool.h"
#include "macrotab.h"
#include "pragma.h"
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
int comma;
SymEntry* Entry;
- kill ();
- NextToken (); /* "prime" the pump */
+ /* Go... */
NextToken ();
- while (curtok != TOK_CEOF) {
+ NextToken ();
+
+ /* Parse until end of input */
+ while (CurTok.Tok != TOK_CEOF) {
- DeclSpec Spec;
+ DeclSpec Spec;
Declaration Decl;
- int NeedStorage;
+ int NeedStorage;
/* Check for empty statements */
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
NextToken ();
continue;
}
/* Check for an ASM statement (which is allowed also on global level) */
- if (curtok == TOK_ASM) {
- doasm ();
+ if (CurTok.Tok == TOK_ASM) {
+ AsmStatement ();
ConsumeSemi ();
continue;
}
/* Check for a #pragma */
- if (curtok == TOK_PRAGMA) {
+ if (CurTok.Tok == TOK_PRAGMA) {
DoPragma ();
continue;
}
ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT);
/* Don't accept illegal storage classes */
- if (Spec.StorageClass == SC_AUTO || Spec.StorageClass == SC_REGISTER) {
- Error (ERR_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_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
CheckEmptyDecl (&Spec);
NextToken ();
continue;
/* Get the symbol flags */
SymFlags = Spec.StorageClass;
- if (IsFunc (Decl.Type)) {
+ if (IsTypeFunc (Decl.Type)) {
SymFlags |= SC_FUNC;
} else {
if (NeedStorage) {
unsigned Size = SizeOf (Decl.Type);
/* Allow initialization */
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
/* We cannot initialize types of unknown size, or
* void types in non ANSI mode.
*/
if (Size == 0) {
- if (!IsVoid (Decl.Type)) {
- if (!IsArray (Decl.Type)) {
- /* Size is unknown and not an array */
- Error (ERR_UNKNOWN_SIZE);
- }
- } else if (ANSI) {
- /* We cannot declare variables of type void */
- Error (ERR_ILLEGAL_TYPE);
- }
+ if (!IsTypeVoid (Decl.Type)) {
+ if (!IsTypeArray (Decl.Type)) {
+ /* Size is unknown and not an array */
+ Error ("Variable `%s' has unknown size", Decl.Ident);
+ }
+ } else if (ANSI) {
+ /* We cannot declare variables of type void */
+ Error ("Illegal type for variable `%s'", Decl.Ident);
+ }
}
- /* Switch to the data segment */
- g_usedata ();
+ /* Switch to the data or rodata segment */
+ if (IsQualConst (Decl.Type)) {
+ g_userodata ();
+ } else {
+ g_usedata ();
+ }
/* Define a label */
g_defgloblabel (Entry->Name);
ParseInit (Entry->Type);
} else {
- if (IsVoid (Decl.Type)) {
+ if (IsTypeVoid (Decl.Type)) {
/* We cannot declare variables of type void */
- Error (ERR_ILLEGAL_TYPE);
- } else if (Size == 0) {
- /* Size is unknown */
- Error (ERR_UNKNOWN_SIZE);
+ Error ("Illegal type for variable `%s'", 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);
+ }
}
}
/* Check for end of declaration list */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
comma = 1;
} else {
}
/* Function declaration? */
- if (IsFunc (Decl.Type)) {
+ if (Entry && IsTypeFunc (Entry->Type)) {
/* Function */
if (!comma) {
-
- if (curtok == TOK_SEMI) {
-
+ if (CurTok.Tok == TOK_SEMI) {
/* Prototype only */
NextToken ();
-
- } else {
- if (Entry) {
- NewFunc (Entry);
- }
+ } else if (Entry) {
+ /* Function body definition */
+ if (SymIsDef (Entry)) {
+ Error ("Body for function `%s' has already been defined",
+ Entry->Name);
+ }
+ NewFunc (Entry);
}
}
-void Compile (void)
+void Compile (const char* FileName)
/* Top level compile routine. Will setup things and call the parser. */
{
- char* Path;
-
-
- /* Setup variables */
- LiteralLabel = GetLabel ();
-
- /* 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);
- }
+ char Buf[20];
+ char DateStr[20];
+ char TimeStr[20];
+ time_t Time;
+ struct tm* TM;
+
+ /* Since strftime is locale dependent, we need the abbreviated month names
+ * in english.
+ */
+ static const char MonthNames[12][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
/* Add macros that are always defined */
- AddNumericMacro ("__CC65__", (VER_MAJOR * 0x100) + (VER_MINOR * 0x10) + VER_PATCH);
+ DefineNumericMacro ("__CC65__", VERSION);
/* Strict ANSI macro */
if (ANSI) {
- AddNumericMacro ("__STRICT_ANSI__", 1);
+ DefineNumericMacro ("__STRICT_ANSI__", 1);
}
- /* Optimization macros */
+ /* 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 (Optimize) {
- AddNumericMacro ("__OPT__", 1);
+ DefineNumericMacro ("__OPT__", 1);
if (FavourSize == 0) {
- AddNumericMacro ("__OPT_i__", 1);
+ DefineNumericMacro ("__OPT_i__", 1);
}
- if (EnableRegVars) {
- AddNumericMacro ("__OPT_r__", 1);
+ if (IS_Get (&EnableRegVars)) {
+ DefineNumericMacro ("__OPT_r__", 1);
}
- if (InlineStdFuncs) {
- AddNumericMacro ("__OPT_s__", 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);
+ strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM);
+ DefineTextMacro ("__DATE__", DateStr);
+ DefineTextMacro ("__TIME__", TimeStr);
+
+ /* Initialize the literal pool */
+ InitLiteralPool ();
+
/* Create the base lexical level */
EnterGlobalLevel ();
/* Generate the code generator preamble */
g_preamble ();
+ /* Open the input file */
+ OpenMainFile (FileName);
+
/* Ok, start the ball rolling... */
Parse ();
- /* Dump literal pool. */
+ /* Dump the literal pool. */
DumpLiteralPool ();
/* Write imported/exported symbols */
EmitExternals ();
if (Debug) {
- PrintLiteralStats (stdout);
+ PrintLiteralPoolStats (stdout);
PrintMacroStats (stdout);
}
+