From 9cc25f13b6aabc4fd299c54c9c38c5825689eb47 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 12 Jun 2000 18:31:40 +0000 Subject: [PATCH] Added support for old style (K&R) function declarations. Several renames for better readibility. Removed separate struct and enum symbol tables in favour of one tag table. Check for some more error conditions or dubious constructs. git-svn-id: svn://svn.cc65.org/cc65/trunk@62 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/compile.c | 322 +++++++++++++++++++++++++ src/cc65/compile.h | 57 +++++ src/cc65/datatype.c | 7 +- src/cc65/declare.c | 504 +++++++++++++++++++++++++-------------- src/cc65/declare.h | 15 +- src/cc65/error.c | 2 + src/cc65/error.h | 4 +- src/cc65/expr.c | 288 +++++++++++----------- src/cc65/funcdesc.c | 5 +- src/cc65/funcdesc.h | 26 +- src/cc65/function.c | 4 +- src/cc65/goto.c | 10 +- src/cc65/locals.c | 43 ++-- src/cc65/main.c | 266 +-------------------- src/cc65/make/gcc.mak | 1 + src/cc65/make/watcom.mak | 2 + src/cc65/pragma.c | 10 +- src/cc65/preproc.c | 6 +- src/cc65/scanner.c | 221 ++++++++--------- src/cc65/scanner.h | 221 ++++++++--------- src/cc65/stmt.c | 104 ++++---- src/cc65/symtab.c | 136 ++++++----- src/cc65/symtab.h | 11 +- 23 files changed, 1279 insertions(+), 986 deletions(-) create mode 100644 src/cc65/compile.c create mode 100644 src/cc65/compile.h diff --git a/src/cc65/compile.c b/src/cc65/compile.c new file mode 100644 index 000000000..5225d9b68 --- /dev/null +++ b/src/cc65/compile.c @@ -0,0 +1,322 @@ +/*****************************************************************************/ +/* */ +/* compile.c */ +/* */ +/* Top level compiler subroutine */ +/* */ +/* */ +/* */ +/* (C) 2000 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#include + +#include "../common/version.h" + +#include "asmlabel.h" +#include "codegen.h" +#include "declare.h" +#include "error.h" +#include "expr.h" +#include "function.h" +#include "global.h" +#include "include.h" +#include "io.h" +#include "litpool.h" +#include "macrotab.h" +#include "pragma.h" +#include "symtab.h" +#include "compile.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +static void Parse (void) +/* Process all input text. + * At this level, only static declarations, defines, includes, and function + * definitions are legal.... + */ +{ + int comma; + SymEntry* Entry; + + kill (); + NextToken (); /* "prime" the pump */ + NextToken (); + while (curtok != TOK_CEOF) { + + DeclSpec Spec; + Declaration Decl; + int NeedStorage; + + /* Check for empty statements */ + if (curtok == TOK_SEMI) { + NextToken (); + continue; + } + + /* Check for an ASM statement (which is allowed also on global level) */ + if (curtok == TOK_ASM) { + doasm (); + ConsumeSemi (); + continue; + } + + /* Check for a #pragma */ + if (curtok == TOK_PRAGMA) { + DoPragma (); + continue; + } + + /* Read variable defs and functions */ + 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; + } + + /* Check if this is only a type declaration */ + if (curtok == TOK_SEMI) { + CheckEmptyDecl (&Spec); + NextToken (); + 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; + + /* Read the next declaration */ + ParseDecl (&Spec, &Decl, DM_NEED_IDENT); + if (Decl.Ident[0] == '\0') { + NextToken (); + break; + } + + /* Get the symbol flags */ + SymFlags = Spec.StorageClass; + if (IsFunc (Decl.Type)) { + SymFlags |= SC_FUNC; + } else { + if (NeedStorage) { + /* We will allocate storage, variable is defined */ + SymFlags |= SC_STORAGE | SC_DEF; + } + } + + /* Add an entry to the symbol table */ + Entry = AddGlobalSym (Decl.Ident, Decl.Type, SymFlags); + + /* Reserve storage for the variable if we need to */ + if (SymFlags & SC_STORAGE) { + + /* Get the size of the variable */ + unsigned Size = SizeOf (Decl.Type); + + /* Allow initialization */ + if (curtok == 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); + } + } + + /* Switch to the data segment */ + g_usedata (); + + /* Define a label */ + g_defgloblabel (Entry->Name); + + /* Skip the '=' */ + NextToken (); + + /* Parse the initialization */ + ParseInit (Entry->Type); + } else { + + if (IsVoid (Decl.Type)) { + /* We cannot declare variables of type void */ + Error (ERR_ILLEGAL_TYPE); + } else if (Size == 0) { + /* Size is unknown */ + Error (ERR_UNKNOWN_SIZE); + } + + /* Switch to the BSS segment */ + g_usebss (); + + /* Define a label */ + g_defgloblabel (Entry->Name); + + /* Allocate space for uninitialized variable */ + g_res (SizeOf (Entry->Type)); + } + + } + + /* Check for end of declaration list */ + if (curtok == TOK_COMMA) { + NextToken (); + comma = 1; + } else { + break; + } + } + + /* Function declaration? */ + if (IsFunc (Decl.Type)) { + + /* Function */ + if (!comma) { + + if (curtok == TOK_SEMI) { + + /* Prototype only */ + NextToken (); + + } else { + if (Entry) { + NewFunc (Entry); + } + } + } + + } else { + + /* Must be followed by a semicolon */ + ConsumeSemi (); + + } + } +} + + + +void Compile (void) +/* Top level compile routine. Will setup things and call the parser. */ +{ + char* Path; + + + /* Setup variables */ + filetab[0].f_iocb = inp; + 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); + } + + /* Add macros that are always defined */ + AddNumericMacro ("__CC65__", (VER_MAJOR * 0x100) + (VER_MINOR * 0x10) + VER_PATCH); + + /* Strict ANSI macro */ + if (ANSI) { + AddNumericMacro ("__STRICT_ANSI__", 1); + } + + /* Optimization macros */ + if (Optimize) { + AddNumericMacro ("__OPT__", 1); + if (FavourSize == 0) { + AddNumericMacro ("__OPT_i__", 1); + } + if (EnableRegVars) { + AddNumericMacro ("__OPT_r__", 1); + } + if (InlineStdFuncs) { + AddNumericMacro ("__OPT_s__", 1); + } + } + + /* Create the base lexical level */ + EnterGlobalLevel (); + + /* Generate the code generator preamble */ + g_preamble (); + + /* Ok, start the ball rolling... */ + Parse (); + + /* Dump literal pool. */ + DumpLiteralPool (); + + /* Write imported/exported symbols */ + EmitExternals (); + + if (Debug) { + PrintLiteralStats (stdout); + PrintMacroStats (stdout); + } + + /* Leave the main lexical level */ + LeaveGlobalLevel (); + + /* Print an error report */ + ErrorReport (); +} + + + diff --git a/src/cc65/compile.h b/src/cc65/compile.h new file mode 100644 index 000000000..d0f6f3816 --- /dev/null +++ b/src/cc65/compile.h @@ -0,0 +1,57 @@ +/*****************************************************************************/ +/* */ +/* compile.h */ +/* */ +/* Top level compiler subroutine */ +/* */ +/* */ +/* */ +/* (C) 2000 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef COMPILE_H +#define COMPILE_H + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +void Compile (void); +/* Top level compile routine. Will setup things and call the parser. */ + + + +/* End of compile.h */ + +#endif + + + diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 21d2320de..330a08eb6 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -184,10 +184,9 @@ type* GetImplicitFuncType (void) type* T = TypeAlloc (1 + DECODE_SIZE + 2); /* Prepare the function descriptor */ - F->Flags = FD_IMPLICIT | FD_ELLIPSIS; - F->SymTab = &EmptySymTab; - F->StructTab = &EmptySymTab; - F->EnumTab = &EmptySymTab; + F->Flags = FD_IMPLICIT | FD_EMPTY | FD_ELLIPSIS; + F->SymTab = &EmptySymTab; + F->TagTab = &EmptySymTab; /* Fill the type string */ T [0] = T_FUNC; diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 8c40fa81b..30b9e8af1 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -48,9 +48,9 @@ static void ParseTypeSpec (DeclSpec* D, int Default); static void optional_modifiers (void) /* Eat optional "const" or "volatile" tokens */ { - while (curtok == CONST || curtok == VOLATILE) { + while (curtok == TOK_CONST || curtok == TOK_VOLATILE) { /* Skip it */ - gettok (); + NextToken (); } } @@ -59,9 +59,9 @@ static void optional_modifiers (void) static void optionalint (void) /* Eat an optional "int" token */ { - if (curtok == INT) { + if (curtok == TOK_INT) { /* Skip it */ - gettok (); + NextToken (); } } @@ -70,9 +70,9 @@ static void optionalint (void) static void optionalsigned (void) /* Eat an optional "signed" token */ { - if (curtok == SIGNED) { + if (curtok == TOK_SIGNED) { /* Skip it */ - gettok (); + NextToken (); } } @@ -107,29 +107,29 @@ static void ParseStorageClass (DeclSpec* D, unsigned DefStorage) /* Check the storage class given */ switch (curtok) { - case EXTERN: + case TOK_EXTERN: D->StorageClass = SC_EXTERN | SC_STATIC; - gettok (); + NextToken (); break; - case STATIC: + case TOK_STATIC: D->StorageClass = SC_STATIC; - gettok (); + NextToken (); break; - case REGISTER: + case TOK_REGISTER: D->StorageClass = SC_REGISTER | SC_STATIC; - gettok (); + NextToken (); break; - case AUTO: + case TOK_AUTO: D->StorageClass = SC_AUTO; - gettok (); + NextToken (); break; - case TYPEDEF: + case TOK_TYPEDEF: D->StorageClass = SC_TYPEDEF; - gettok (); + NextToken (); break; default: @@ -149,31 +149,31 @@ static void ParseEnumDecl (void) ident Ident; /* Accept forward definitions */ - if (curtok != LCURLY) { + if (curtok != TOK_LCURLY) { return; } /* Skip the opening curly brace */ - gettok (); + NextToken (); /* Read the enum tags */ EnumVal = 0; - while (curtok != RCURLY) { + while (curtok != TOK_RCURLY) { /* We expect an identifier */ - if (curtok != IDENT) { + if (curtok != TOK_IDENT) { Error (ERR_IDENT_EXPECTED); continue; } /* Remember the identifier and skip it */ strcpy (Ident, CurTok.Ident); - gettok (); + NextToken (); /* Check for an assigned value */ - if (curtok == ASGN) { + if (curtok == TOK_ASSIGN) { struct expent lval; - gettok (); + NextToken (); constexpr (&lval); EnumVal = lval.e_const; } @@ -182,9 +182,9 @@ static void ParseEnumDecl (void) AddEnumSym (Ident, EnumVal++); /* Check for end of definition */ - if (curtok != COMMA) + if (curtok != TOK_COMMA) break; - gettok (); + NextToken (); } ConsumeRCurly (); } @@ -201,30 +201,33 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType) SymEntry* Entry; - if (curtok != LCURLY) { + if (curtok != TOK_LCURLY) { /* Just a forward declaration. Try to find a struct with the given * name. If there is none, insert a forward declaration into the * current lexical level. */ - Entry = FindStructSym (Name); - if (Entry == 0 || Entry->Flags != SC_STRUCT) { + Entry = FindTagSym (Name); + if (Entry == 0) { Entry = AddStructSym (Name, 0, 0); + } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) { + /* Already defined in the level but no struct */ + Error (ERR_SYMBOL_KIND); } - return Entry; + return Entry; } /* Add a forward declaration for the struct in the current lexical level */ Entry = AddStructSym (Name, 0, 0); /* Skip the curly brace */ - gettok (); + NextToken (); /* Enter a new lexical level for the struct */ EnterStructLevel (); /* Parse struct fields */ Size = 0; - while (curtok != RCURLY) { + while (curtok != TOK_RCURLY) { /* Get the type of the entry */ DeclSpec Spec; @@ -251,15 +254,15 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType) } } - if (curtok != COMMA) + if (curtok != TOK_COMMA) break; - gettok (); + NextToken (); } ConsumeSemi (); } /* Skip the closing brace */ - gettok (); + NextToken (); /* Remember the symbol table and leave the struct level */ FieldTab = GetSymTab (); @@ -274,9 +277,9 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType) static void ParseTypeSpec (DeclSpec* D, int Default) /* Parse a type specificier */ { - ident Ident; - SymEntry* Entry; - type StructType; + ident Ident; + SymEntry* Entry; + type StructType; /* Assume have an explicit type */ D->Flags &= ~DS_DEF_TYPE; @@ -287,22 +290,22 @@ static void ParseTypeSpec (DeclSpec* D, int Default) /* Look at the data type */ switch (curtok) { - case VOID: - gettok (); + case TOK_VOID: + NextToken (); D->Type[0] = T_VOID; D->Type[1] = T_END; break; - case CHAR: - gettok (); + case TOK_CHAR: + NextToken (); D->Type[0] = GetDefaultChar(); D->Type[1] = T_END; break; - case LONG: - gettok (); - if (curtok == UNSIGNED) { - gettok (); + case TOK_LONG: + NextToken (); + if (curtok == TOK_UNSIGNED) { + NextToken (); optionalint (); D->Type[0] = T_ULONG; D->Type[1] = T_END; @@ -314,10 +317,10 @@ static void ParseTypeSpec (DeclSpec* D, int Default) } break; - case SHORT: - gettok (); - if (curtok == UNSIGNED) { - gettok (); + case TOK_SHORT: + NextToken (); + if (curtok == TOK_UNSIGNED) { + NextToken (); optionalint (); D->Type[0] = T_USHORT; D->Type[1] = T_END; @@ -329,38 +332,38 @@ static void ParseTypeSpec (DeclSpec* D, int Default) } break; - case INT: - gettok (); + case TOK_INT: + NextToken (); D->Type[0] = T_INT; D->Type[1] = T_END; break; - case SIGNED: - gettok (); + case TOK_SIGNED: + NextToken (); switch (curtok) { - case CHAR: - gettok (); + case TOK_CHAR: + NextToken (); D->Type[0] = T_CHAR; D->Type[1] = T_END; break; - case SHORT: - gettok (); + case TOK_SHORT: + NextToken (); optionalint (); D->Type[0] = T_SHORT; D->Type[1] = T_END; break; - case LONG: - gettok (); + case TOK_LONG: + NextToken (); optionalint (); D->Type[0] = T_LONG; D->Type[1] = T_END; break; - case INT: - gettok (); + case TOK_INT: + NextToken (); /* FALL THROUGH */ default: @@ -370,32 +373,32 @@ static void ParseTypeSpec (DeclSpec* D, int Default) } break; - case UNSIGNED: - gettok (); + case TOK_UNSIGNED: + NextToken (); switch (curtok) { - case CHAR: - gettok (); + case TOK_CHAR: + NextToken (); D->Type[0] = T_UCHAR; D->Type[1] = T_END; - break; + break; - case SHORT: - gettok (); + case TOK_SHORT: + NextToken (); optionalint (); D->Type[0] = T_USHORT; D->Type[1] = T_END; break; - case LONG: - gettok (); + case TOK_LONG: + NextToken (); optionalint (); D->Type[0] = T_ULONG; D->Type[1] = T_END; break; - case INT: - gettok (); + case TOK_INT: + NextToken (); /* FALL THROUGH */ default: @@ -405,16 +408,19 @@ static void ParseTypeSpec (DeclSpec* D, int Default) } break; - case STRUCT: - case UNION: - StructType = (curtok == STRUCT)? T_STRUCT : T_UNION; - gettok (); - if (curtok == IDENT) { + case TOK_STRUCT: + case TOK_UNION: + StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION; + NextToken (); + /* */ + if (curtok == TOK_IDENT) { strcpy (Ident, CurTok.Ident); - gettok (); + NextToken (); } else { AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union"); } + /* Remember we have an extra type decl */ + D->Flags |= DS_EXTRA_TYPE; /* Declare the struct in the current scope */ Entry = ParseStructDecl (Ident, StructType); /* Encode the struct entry into the type */ @@ -423,22 +429,39 @@ static void ParseTypeSpec (DeclSpec* D, int Default) D->Type[DECODE_SIZE+1] = T_END; break; - case ENUM: - gettok (); - if (curtok != LCURLY) { - /* Named enum */ - Consume (IDENT, ERR_IDENT_EXPECTED); + case TOK_ENUM: + NextToken (); + if (curtok != TOK_LCURLY) { + /* Named enum */ + if (curtok == TOK_IDENT) { + /* Find an entry with this name */ + Entry = FindTagSym (CurTok.Ident); + if (Entry) { + if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) { + Error (ERR_SYMBOL_KIND); + } + } else { + /* Insert entry into table ### */ + } + /* Skip the identifier */ + NextToken (); + } else { + Error (ERR_IDENT_EXPECTED); + } } + /* Remember we have an extra type decl */ + D->Flags |= DS_EXTRA_TYPE; + /* Parse the enum decl */ ParseEnumDecl (); D->Type[0] = T_INT; D->Type[1] = T_END; break; - case IDENT: + case TOK_IDENT: Entry = FindSym (CurTok.Ident); if (Entry && IsTypeDef (Entry)) { /* It's a typedef */ - gettok (); + NextToken (); TypeCpy (D->Type, Entry->Type); break; } @@ -460,39 +483,116 @@ static void ParseTypeSpec (DeclSpec* D, int Default) -static FuncDesc* ParseFuncDecl (void) -/* Parse the argument list of a function. */ +static type* ParamTypeCvt (type* T) +/* If T is an array, convert it to a pointer else do nothing. Return the + * resulting type. + */ { - unsigned UnnamedCount = 0; - unsigned Offs; - SymEntry* Sym; - type* Type; + if (IsArray (T)) { + T += DECODE_SIZE; + T[0] = T_PTR; + } + return T; +} - /* Create a new function descriptor */ - FuncDesc* F = NewFuncDesc (); - /* Enter a new lexical level */ - EnterFunctionLevel (); - /* Check for an empty or void parameter list */ - if (curtok == RPAREN) { - /* Parameter list is empty */ - F->Flags |= (FD_EMPTY | FD_ELLIPSIS); - } else if (curtok == VOID && nxttok == RPAREN) { - /* Parameter list declared as void */ - gettok (); - F->Flags |= FD_VOID_PARAM; +static void ParseOldStyleParamList (FuncDesc* F) +/* Parse an old style (K&R) parameter list */ +{ + /* Parse params */ + while (curtok != TOK_RPAREN) { + + /* List of identifiers expected */ + if (curtok != TOK_IDENT) { + Error (ERR_IDENT_EXPECTED); + } + + /* Create a symbol table entry with type int */ + AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0); + + /* Count arguments */ + ++F->ParamCount; + + /* Skip the identifier */ + NextToken (); + + /* Check for more parameters */ + if (curtok == TOK_COMMA) { + NextToken (); + } else { + break; + } + } + + /* Skip right paren. We must explicitly check for one here, since some of + * the breaks above bail out without checking. + */ + ConsumeRParen (); + + /* An optional list of type specifications follows */ + while (curtok != TOK_LCURLY) { + + DeclSpec Spec; + + /* Read the declaration specifier */ + ParseDeclSpec (&Spec, SC_AUTO, T_INT); + + /* We accept only auto and register as storage class specifiers, but + * we ignore all this, since we use auto anyway. + */ + if ((Spec.StorageClass & SC_AUTO) == 0 && + (Spec.StorageClass & SC_REGISTER) == 0) { + Error (ERR_ILLEGAL_STORAGE_CLASS); + } + + /* Parse a comma separated variable list */ + while (1) { + + Declaration Decl; + + /* Read the parameter */ + ParseDecl (&Spec, &Decl, DM_NEED_IDENT); + if (Decl.Ident[0] != '\0') { + + /* We have a name given. Search for the symbol */ + SymEntry* Sym = FindLocalSym (Decl.Ident); + if (Sym) { + /* Found it, change the default type to the one given */ + ChangeSymType (Sym, ParamTypeCvt (Decl.Type)); + } else { + Error (ERR_UNKNOWN_IDENT, Decl.Ident); + } + } + + if (curtok == TOK_COMMA) { + NextToken (); + } else { + break; + } + + } + + /* Variable list must be semicolon terminated */ + ConsumeSemi (); } +} + + +static void ParseAnsiParamList (FuncDesc* F) +/* Parse a new style (ANSI) parameter list */ +{ /* Parse params */ - while (curtok != RPAREN) { + while (curtok != TOK_RPAREN) { + + DeclSpec Spec; + Declaration Decl; - DeclSpec Spec; - Declaration Decl; /* Allow an ellipsis as last parameter */ - if (curtok == ELLIPSIS) { - gettok (); + if (curtok == TOK_ELLIPSIS) { + NextToken (); F->Flags |= FD_ELLIPSIS; break; } @@ -518,30 +618,22 @@ static FuncDesc* ParseFuncDecl (void) /* Unnamed symbol. Generate a name that is not user accessible, * then handle the symbol normal. */ - AnonName (Decl.Ident, "param"); - ++UnnamedCount; + AnonName (Decl.Ident, "param"); + F->Flags |= FD_UNNAMED_PARAMS; - /* Clear defined bit on nonames */ - Spec.StorageClass &= ~SC_DEF; - } - - /* If the parameter is an array, convert it to a pointer */ - Type = Decl.Type; - if (IsArray (Type)) { - Type += DECODE_SIZE; - Type[0] = T_PTR; - } + /* Clear defined bit on nonames */ + Spec.StorageClass &= ~SC_DEF; + } /* Create a symbol table entry */ - AddLocalSym (Decl.Ident, Type, Spec.StorageClass, 0); + AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0); /* Count arguments */ ++F->ParamCount; - F->ParamSize += SizeOf (Type); /* Check for more parameters */ - if (curtok == COMMA) { - gettok (); + if (curtok == TOK_COMMA) { + NextToken (); } else { break; } @@ -552,25 +644,64 @@ static FuncDesc* ParseFuncDecl (void) */ ConsumeRParen (); + /* Check if this is a function definition */ + if (curtok == TOK_LCURLY) { + /* Print an error if in strict ANSI mode and we have unnamed + * parameters. + */ + if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) { + Error (ERR_MISSING_PARAM_NAME); + } + } +} + + + +static FuncDesc* ParseFuncDecl (void) +/* Parse the argument list of a function. */ +{ + unsigned Offs; + SymEntry* Sym; + + /* Create a new function descriptor */ + FuncDesc* F = NewFuncDesc (); + + /* Enter a new lexical level */ + EnterFunctionLevel (); + + /* Check for several special parameter lists */ + if (curtok == TOK_RPAREN) { + /* Parameter list is empty */ + F->Flags |= (FD_EMPTY | FD_ELLIPSIS); + } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) { + /* Parameter list declared as void */ + NextToken (); + F->Flags |= FD_VOID_PARAM; + } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) { + /* Old style (K&R) function. Assume variable param list. */ + F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS); + } + + /* Parse params */ + if ((F->Flags & FD_OLDSTYLE) == 0) { + /* New style function */ + ParseAnsiParamList (F); + } else { + /* Old style function */ + ParseOldStyleParamList (F); + } + /* Assign offsets. If the function has a variable parameter list, * there's one additional byte (the arg size). */ Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0; Sym = GetSymTab()->SymTail; while (Sym) { + unsigned Size = SizeOf (Sym->Type); Sym->V.Offs = Offs; - Offs += SizeOf (Sym->Type); - Sym = Sym->PrevSym; - } - - /* Check if this is a function definition */ - if (curtok == LCURLY) { - /* Print an error if in strict ANSI mode and we have unnamed - * parameters. - */ - if (ANSI && UnnamedCount > 0) { - Error (ERR_MISSING_PARAM_NAME); - } + Offs += Size; + F->ParamSize += Size; + Sym = Sym->PrevSym; } /* Leave the lexical level remembering the symbol tables */ @@ -585,22 +716,22 @@ static FuncDesc* ParseFuncDecl (void) static void Decl (Declaration* D, unsigned Mode) /* Recursively process declarators. Build a type array in reverse order. */ { - if (curtok == STAR) { - gettok (); + if (curtok == TOK_STAR) { + NextToken (); /* Allow optional const or volatile modifiers */ optional_modifiers (); Decl (D, Mode); *D->T++ = T_PTR; return; - } else if (curtok == LPAREN) { - gettok (); + } else if (curtok == TOK_LPAREN) { + NextToken (); Decl (D, Mode); ConsumeRParen (); - } else if (curtok == FASTCALL) { + } else if (curtok == TOK_FASTCALL) { /* Remember the current type pointer */ type* T = D->T; /* Skip the fastcall token */ - gettok (); + NextToken (); /* Parse the function */ Decl (D, Mode); /* Set the fastcall flag */ @@ -612,35 +743,35 @@ static void Decl (Declaration* D, unsigned Mode) } return; } else { - /* Things depend on Mode now: + /* Things depend on Mode now: * - Mode == DM_NEED_IDENT means: - * we *must* have a type and a variable identifer. - * - Mode == DM_NO_IDENT means: - * we must have a type but no variable identifer - * (if there is one, it's not read). - * - Mode == DM_ACCEPT_IDENT means: - * we *may* have an identifier. If there is an identifier, - * it is read, but it is no error, if there is none. - */ - if (Mode == DM_NO_IDENT) { - D->Ident[0] = '\0'; - } else if (curtok == IDENT) { + * we *must* have a type and a variable identifer. + * - Mode == DM_NO_IDENT means: + * we must have a type but no variable identifer + * (if there is one, it's not read). + * - Mode == DM_ACCEPT_IDENT means: + * we *may* have an identifier. If there is an identifier, + * it is read, but it is no error, if there is none. + */ + if (Mode == DM_NO_IDENT) { + D->Ident[0] = '\0'; + } else if (curtok == TOK_IDENT) { strcpy (D->Ident, CurTok.Ident); - gettok (); - } else { - if (Mode == DM_NEED_IDENT) { - Error (ERR_IDENT_EXPECTED); - } - D->Ident[0] = '\0'; - return; - } + NextToken (); + } else { + if (Mode == DM_NEED_IDENT) { + Error (ERR_IDENT_EXPECTED); + } + D->Ident[0] = '\0'; + return; + } } - while (curtok == LBRACK || curtok == LPAREN) { - if (curtok == LPAREN) { + while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) { + if (curtok == TOK_LPAREN) { /* Function declaration */ FuncDesc* F; - gettok (); + NextToken (); /* Parse the function declaration */ F = ParseFuncDecl (); *D->T++ = T_FUNC; @@ -649,9 +780,9 @@ static void Decl (Declaration* D, unsigned Mode) } else { /* Array declaration */ unsigned long Size = 0; - gettok (); + NextToken (); /* Read the size if it is given */ - if (curtok != RBRACK) { + if (curtok != TOK_RBRACK) { struct expent lval; constexpr (&lval); Size = lval.e_const; @@ -730,6 +861,19 @@ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType) +void CheckEmptyDecl (const DeclSpec* D) +/* Called after an empty type declaration (that is, a type declaration without + * a variable). Checks if the declaration does really make sense and issues a + * warning if not. + */ +{ + if ((D->Flags & DS_EXTRA_TYPE) == 0) { + Warning (WARN_USELESS_DECL); + } +} + + + static void ParseVoidInit (void) /* Parse an initialization of a void variable (special cc65 extension) */ { @@ -757,7 +901,7 @@ static void ParseVoidInit (void) case T_PTR: case T_ARRAY: if ((lval.e_flags & E_MCTYPE) == E_TCONST) { - /* Make it word sized */ + /* Make it word sized */ lval.e_const &= 0xFFFF; } DefineData (&lval); @@ -774,12 +918,12 @@ static void ParseVoidInit (void) } - if (curtok != COMMA) { + if (curtok != TOK_COMMA) { break; } - gettok (); + NextToken (); - } while (curtok != RCURLY); + } while (curtok != TOK_RCURLY); ConsumeRCurly (); } @@ -810,16 +954,16 @@ static void ParseStructInit (type* Type) /* Get a pointer to the list of symbols */ Entry = Tab->SymHead; - while (curtok != RCURLY) { - if (Entry == NULL) { + while (curtok != TOK_RCURLY) { + if (Entry == 0) { Error (ERR_TOO_MANY_INITIALIZERS); return; } ParseInit (Entry->Type); Entry = Entry->NextSym; - if (curtok != COMMA) + if (curtok != TOK_COMMA) break; - gettok (); + NextToken (); } /* Consume the closing curly brace */ @@ -886,22 +1030,22 @@ void ParseInit (type *tptr) case T_ARRAY: sz = Decode (tptr + 1); t = tptr + DECODE_SIZE + 1; - if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == SCONST) { + if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == TOK_SCONST) { str = GetLiteral (curval); count = strlen (str) + 1; TranslateLiteralPool (curval); /* Translate into target charset */ g_defbytes (str, count); ResetLiteralOffs (curval); /* Remove string from pool */ - gettok (); + NextToken (); } else { ConsumeLCurly (); count = 0; - while (curtok != RCURLY) { + while (curtok != TOK_RCURLY) { ParseInit (tptr + DECODE_SIZE + 1); ++count; - if (curtok != COMMA) + if (curtok != TOK_COMMA) break; - gettok (); + NextToken (); } ConsumeRCurly (); } diff --git a/src/cc65/declare.h b/src/cc65/declare.h index 57bf41516..5ff18ce0a 100644 --- a/src/cc65/declare.h +++ b/src/cc65/declare.h @@ -23,15 +23,16 @@ /* Masks for the Flags field in DeclSpec */ -#define DS_DEF_STORAGE 0x0001U /* Default storage class used */ -#define DS_DEF_TYPE 0x0002U /* Default type used */ +#define DS_DEF_STORAGE 0x0001U /* Default storage class used */ +#define DS_DEF_TYPE 0x0002U /* Default type used */ +#define DS_EXTRA_TYPE 0x0004U /* Extra type declared */ /* Result of ParseDeclSpec */ typedef struct DeclSpec DeclSpec; struct DeclSpec { - unsigned StorageClass; /* One of the SC_xxx flags */ + unsigned StorageClass; /* One of the SC_xxx flags */ type Type [MAXTYPELEN]; /* Type of the declaration spec */ - unsigned Flags; /* Bitmapped flags */ + unsigned Flags; /* Bitmapped flags */ }; /* Result of ParseDecl */ @@ -66,6 +67,12 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode); void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType); /* Parse a declaration specification */ +void CheckEmptyDecl (const DeclSpec* D); +/* Called after an empty type declaration (that is, a type declaration without + * a variable). Checks if the declaration does really make sense and issues a + * warning if not. + */ + void ParseInit (type* tptr); /* Parse initialization of variables */ diff --git a/src/cc65/error.c b/src/cc65/error.c index 4d3250256..56a034246 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -65,6 +65,7 @@ static char* WarnMsg [WARN_COUNT-1] = { "`%s' is defined but never used", "Constant is long", "`/*' found inside a comment", + "Useless declaration", }; @@ -147,6 +148,7 @@ static char* ErrMsg [ERR_COUNT-1] = { "Illegal size of data type", "__fastcall__ is not allowed for C functions", "Variable has unknown size", + "Unknown identifier: `%s'", }; diff --git a/src/cc65/error.h b/src/cc65/error.h index 6e2912c9e..e5e72ece2 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -60,7 +60,8 @@ enum Warnings { WARN_UNUSED_ITEM, WARN_CONSTANT_IS_LONG, WARN_NESTED_COMMENT, - WARN_COUNT /* Warning count */ + WARN_USELESS_DECL, + WARN_COUNT /* Warning count */ }; /* Error numbers */ @@ -142,6 +143,7 @@ enum Errors { ERR_ILLEGAL_SIZE, ERR_FASTCALL, ERR_UNKNOWN_SIZE, + ERR_UNKNOWN_IDENT, ERR_COUNT /* Error count */ }; diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 3a0d023bf..10d000782 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -49,30 +49,30 @@ typedef struct { } GenDesc; /* Descriptors for the operations */ -static GenDesc GenMUL = { STAR, GEN_NOPUSH, g_mul }; -static GenDesc GenDIV = { DIV, GEN_NOPUSH, g_div }; -static GenDesc GenMOD = { MOD, GEN_NOPUSH, g_mod }; -static GenDesc GenASL = { ASL, GEN_NOPUSH, g_asl }; -static GenDesc GenASR = { ASR, GEN_NOPUSH, g_asr }; -static GenDesc GenLT = { LT, GEN_NOPUSH, g_lt }; -static GenDesc GenLE = { LE, GEN_NOPUSH, g_le }; -static GenDesc GenGE = { GE, GEN_NOPUSH, g_ge }; -static GenDesc GenGT = { GT, GEN_NOPUSH, g_gt }; -static GenDesc GenEQ = { EQ, GEN_NOPUSH, g_eq }; -static GenDesc GenNE = { NE, GEN_NOPUSH, g_ne }; -static GenDesc GenAND = { AMP, GEN_NOPUSH, g_and }; -static GenDesc GenXOR = { XOR, GEN_NOPUSH, g_xor }; -static GenDesc GenOR = { BAR, GEN_NOPUSH, g_or }; -static GenDesc GenPASGN = { PASGN, GEN_NOPUSH, g_add }; -static GenDesc GenSASGN = { SASGN, GEN_NOPUSH, g_sub }; -static GenDesc GenMASGN = { MASGN, GEN_NOPUSH, g_mul }; -static GenDesc GenDASGN = { DASGN, GEN_NOPUSH, g_div }; -static GenDesc GenMOASGN = { MOASGN, GEN_NOPUSH, g_mod }; -static GenDesc GenSLASGN = { SLASGN, GEN_NOPUSH, g_asl }; -static GenDesc GenSRASGN = { SRASGN, GEN_NOPUSH, g_asr }; -static GenDesc GenAASGN = { AASGN, GEN_NOPUSH, g_and }; -static GenDesc GenXOASGN = { XOASGN, GEN_NOPUSH, g_xor }; -static GenDesc GenOASGN = { OASGN, GEN_NOPUSH, g_or }; +static GenDesc GenMUL = { TOK_STAR, GEN_NOPUSH, g_mul }; +static GenDesc GenDIV = { TOK_DIV, GEN_NOPUSH, g_div }; +static GenDesc GenMOD = { TOK_MOD, GEN_NOPUSH, g_mod }; +static GenDesc GenASL = { TOK_SHL, GEN_NOPUSH, g_asl }; +static GenDesc GenASR = { TOK_SHR, GEN_NOPUSH, g_asr }; +static GenDesc GenLT = { TOK_LT, GEN_NOPUSH, g_lt }; +static GenDesc GenLE = { TOK_LE, GEN_NOPUSH, g_le }; +static GenDesc GenGE = { TOK_GE, GEN_NOPUSH, g_ge }; +static GenDesc GenGT = { TOK_GT, GEN_NOPUSH, g_gt }; +static GenDesc GenEQ = { TOK_EQ, GEN_NOPUSH, g_eq }; +static GenDesc GenNE = { TOK_NE, GEN_NOPUSH, g_ne }; +static GenDesc GenAND = { TOK_AND, GEN_NOPUSH, g_and }; +static GenDesc GenXOR = { TOK_XOR, GEN_NOPUSH, g_xor }; +static GenDesc GenOR = { TOK_OR, GEN_NOPUSH, g_or }; +static GenDesc GenPASGN = { TOK_PLUS_ASSIGN, GEN_NOPUSH, g_add }; +static GenDesc GenSASGN = { TOK_MINUS_ASSIGN, GEN_NOPUSH, g_sub }; +static GenDesc GenMASGN = { TOK_MUL_ASSIGN, GEN_NOPUSH, g_mul }; +static GenDesc GenDASGN = { TOK_DIV_ASSIGN, GEN_NOPUSH, g_div }; +static GenDesc GenMOASGN = { TOK_MOD_ASSIGN, GEN_NOPUSH, g_mod }; +static GenDesc GenSLASGN = { TOK_SHL_ASSIGN, GEN_NOPUSH, g_asl }; +static GenDesc GenSRASGN = { TOK_SHR_ASSIGN, GEN_NOPUSH, g_asr }; +static GenDesc GenAASGN = { TOK_AND_ASSIGN, GEN_NOPUSH, g_and }; +static GenDesc GenXOASGN = { TOK_XOR_ASSIGN, GEN_NOPUSH, g_xor }; +static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; @@ -346,37 +346,37 @@ static int kcalc (int tok, long val1, long val2) /* Calculate an operation with left and right operand constant. */ { switch (tok) { - case EQ: + case TOK_EQ: return (val1 == val2); - case NE: + case TOK_NE: return (val1 != val2); - case LT: + case TOK_LT: return (val1 < val2); - case LE: + case TOK_LE: return (val1 <= val2); - case GE: + case TOK_GE: return (val1 >= val2); - case GT: + case TOK_GT: return (val1 > val2); - case BAR: + case TOK_OR: return (val1 | val2); - case XOR: + case TOK_XOR: return (val1 ^ val2); - case AMP: + case TOK_AND: return (val1 & val2); - case ASR: + case TOK_SHR: return (val1 >> val2); - case ASL: + case TOK_SHL: return (val1 << val2); - case STAR: + case TOK_STAR: return (val1 * val2); - case DIV: + case TOK_DIV: if (val2 == 0) { Error (ERR_DIV_BY_ZERO); return 0x7FFFFFFF; } return (val1 / val2); - case MOD: + case TOK_MOD: if (val2 == 0) { Error (ERR_MOD_BY_ZERO); return 0; @@ -411,11 +411,11 @@ static int istypeexpr (void) { SymEntry* Entry; - return curtok == LPAREN && ( - (nxttok >= FIRSTTYPE && nxttok <= LASTTYPE) || - (nxttok == CONST) || - (nxttok == IDENT && - (Entry = FindSym (NextTok.Ident)) != 0 && + return curtok == TOK_LPAREN && ( + (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) || + (nxttok == TOK_CONST) || + (nxttok == TOK_IDENT && + (Entry = FindSym (NextTok.Ident)) != 0 && IsTypeDef (Entry)) ); } @@ -531,7 +531,7 @@ static void callfunction (struct expent* lval) ParamSize = 0; ParamCount = 0; Ellipsis = 0; - while (curtok != RPAREN) { + while (curtok != TOK_RPAREN) { /* Add a hint for the optimizer */ AddCodeHint ("param:start"); @@ -606,10 +606,10 @@ static void callfunction (struct expent* lval) AddCodeHint ("param:end"); /* Check for end of argument list */ - if (curtok != COMMA) { + if (curtok != TOK_COMMA) { break; } - gettok (); + NextToken (); } /* We need the closing bracket here */ @@ -644,13 +644,13 @@ void doasm (void) */ { /* Skip the ASM */ - gettok (); + NextToken (); /* Need left parenthesis */ ConsumeLParen (); /* String literal */ - if (curtok != SCONST) { + if (curtok != TOK_SCONST) { Error (ERR_STRLIT_EXPECTED); } else { /* Write the string directly into the output, followed by a newline */ @@ -665,7 +665,7 @@ void doasm (void) } /* Skip the string token */ - gettok (); + NextToken (); /* Closing paren needed */ ConsumeRParen (); @@ -682,19 +682,19 @@ static int primary (struct expent* lval) lval->e_test = 0; /* Character and integer constants. */ - if (curtok == ICONST || curtok == CCONST) { + if (curtok == TOK_ICONST || curtok == TOK_CCONST) { lval->e_flags = E_MCONST | E_TCONST; lval->e_tptr = curtype; lval->e_const = curval; - gettok (); + NextToken (); return 0; } /* Process parenthesized subexpression by calling the whole parser * recursively. */ - if (curtok == LPAREN) { - gettok (); + if (curtok == TOK_LPAREN) { + NextToken (); memset (lval, 0, sizeof (*lval)); /* Remove any attributes */ k = hie0 (lval); ConsumeRParen (); @@ -713,7 +713,7 @@ static int primary (struct expent* lval) } /* Identifier? */ - if (curtok == IDENT) { + if (curtok == TOK_IDENT) { SymEntry* Sym; ident Ident; @@ -725,7 +725,7 @@ static int primary (struct expent* lval) if (Sym) { /* We found the symbol - skip the name token */ - gettok (); + NextToken (); /* The expression type is the symbol type */ lval->e_tptr = Sym->Type; @@ -791,10 +791,10 @@ static int primary (struct expent* lval) /* We did not find the symbol. Remember the name, then skip it */ strcpy (Ident, CurTok.Ident); - gettok (); + NextToken (); /* IDENT is either an auto-declared function or an undefined variable. */ - if (curtok == LPAREN) { + if (curtok == TOK_LPAREN) { /* Declare a function returning int. For that purpose, prepare a * function signature for a function having an empty param list * and returning int. @@ -821,16 +821,16 @@ static int primary (struct expent* lval) } /* String literal? */ - if (curtok == SCONST) { + if (curtok == TOK_SCONST) { lval->e_flags = E_MCONST | E_TLIT; lval->e_const = curval; lval->e_tptr = GetCharArrayType (strlen (GetLiteral (curval))); - gettok (); + NextToken (); return 0; } /* ASM statement? */ - if (curtok == ASM) { + if (curtok == TOK_ASM) { doasm (); lval->e_tptr = type_void; lval->e_flags = E_MEXPR; @@ -839,12 +839,12 @@ static int primary (struct expent* lval) } /* __AX__ and __EAX__ pseudo values? */ - if (curtok == AX || curtok == EAX) { - lval->e_tptr = (curtok == AX)? type_uint : type_ulong; + if (curtok == TOK_AX || curtok == TOK_EAX) { + lval->e_tptr = (curtok == TOK_AX)? type_uint : type_ulong; lval->e_flags = E_MREG; lval->e_test &= ~E_CC; lval->e_const = 0; - gettok (); + NextToken (); return 1; /* May be used as lvalue */ } @@ -873,7 +873,7 @@ static int arrayref (int k, struct expent* lval) /* Skip the bracket */ - gettok (); + NextToken (); /* Get the type of left side */ tptr1 = lval->e_tptr; @@ -1098,8 +1098,8 @@ static int structref (int k, struct expent* lval) int flags; /* Skip the token and check for an identifier */ - gettok (); - if (curtok != IDENT) { + NextToken (); + if (curtok != TOK_IDENT) { Error (ERR_IDENT_EXPECTED); lval->e_tptr = type_int; return 0; @@ -1107,7 +1107,7 @@ static int structref (int k, struct expent* lval) /* Get the symbol table entry and check for a struct field */ strcpy (Ident, CurTok.Ident); - gettok (); + NextToken (); Field = FindStructField (lval->e_tptr, Ident); if (Field == 0) { Error (ERR_STRUCT_FIELD_MISMATCH, Ident); @@ -1143,22 +1143,22 @@ static int hie11 (struct expent *lval) k = primary (lval); - if (curtok < LBRACK || curtok > PREF) { + if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) { /* Not for us */ return k; } while (1) { - if (curtok == LBRACK) { + if (curtok == TOK_LBRACK) { /* Array reference */ k = arrayref (k, lval); - } else if (curtok == LPAREN) { + } else if (curtok == TOK_LPAREN) { /* Function call. Skip the opening parenthesis */ - gettok (); + NextToken (); tptr = lval->e_tptr; if (IsFunc (tptr) || IsFuncPtr (tptr)) { if (IsFuncPtr (tptr)) { @@ -1175,14 +1175,14 @@ static int hie11 (struct expent *lval) } k = 0; - } else if (curtok == DOT) { + } else if (curtok == TOK_DOT) { if (!IsStruct (lval->e_tptr)) { Error (ERR_STRUCT_EXPECTED); } k = structref (0, lval); - } else if (curtok == PREF) { + } else if (curtok == TOK_PTR_REF) { tptr = lval->e_tptr; if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) { @@ -1242,7 +1242,7 @@ static void pre_incdec (struct expent* lval, void (*inc) (unsigned, unsigned lon unsigned flags; unsigned long val; - gettok (); + NextToken (); if ((k = hie10 (lval)) == 0) { Error (ERR_LVALUE_EXPECTED); return; @@ -1321,7 +1321,7 @@ static void post_incdec (struct expent *lval, int k, void (*inc) (unsigned, unsi { unsigned flags; - gettok (); + NextToken (); if (k == 0) { Error (ERR_LVALUE_EXPECTED); return; @@ -1360,15 +1360,15 @@ static void unaryop (int tok, struct expent* lval) int k; unsigned flags; - gettok (); + NextToken (); k = hie10 (lval); if (k == 0 && lval->e_flags & E_MCONST) { /* Value is constant */ switch (tok) { - case MINUS: lval->e_const = -lval->e_const; break; - case PLUS: break; - case COMP: lval->e_const = ~lval->e_const; break; - default: Internal ("Unexpected token: %d", tok); + case TOK_MINUS: lval->e_const = -lval->e_const; break; + case TOK_PLUS: break; + case TOK_COMP: lval->e_const = ~lval->e_const; break; + default: Internal ("Unexpected token: %d", tok); } } else { /* Value is not constant */ @@ -1379,9 +1379,9 @@ static void unaryop (int tok, struct expent* lval) /* Handle the operation */ switch (tok) { - case MINUS: g_neg (flags); break; - case PLUS: break; - case COMP: g_com (flags); break; + case TOK_MINUS: g_neg (flags); break; + case TOK_PLUS: break; + case TOK_COMP: g_com (flags); break; default: Internal ("Unexpected token: %d", tok); } lval->e_flags = E_MEXPR; @@ -1398,7 +1398,7 @@ static int typecast (struct expent* lval) unsigned rflags; /* Skip the left paren */ - gettok (); + NextToken (); /* Read the type */ ParseType (Type); @@ -1438,22 +1438,22 @@ static int hie10 (struct expent* lval) switch (curtok) { - case INC: + case TOK_INC: pre_incdec (lval, g_inc); return 0; - case DEC: + case TOK_DEC: pre_incdec (lval, g_dec); return 0; - case PLUS: - case MINUS: - case COMP: + case TOK_PLUS: + case TOK_MINUS: + case TOK_COMP: unaryop (curtok, lval); return 0; - case BANG: - gettok (); + case TOK_BOOL_NOT: + NextToken (); if (evalexpr (CF_NONE, hie10, lval) == 0) { /* Constant expression */ lval->e_const = !lval->e_const; @@ -1464,8 +1464,8 @@ static int hie10 (struct expent* lval) } return 0; /* expr not storable */ - case STAR: - gettok (); + case TOK_STAR: + NextToken (); if (evalexpr (CF_NONE, hie10, lval) != 0) { /* Expression is not const, indirect value loaded into primary */ lval->e_flags = E_MEXPR; @@ -1479,11 +1479,11 @@ static int hie10 (struct expent* lval) } return 1; - case AMP: - gettok (); + case TOK_AND: + NextToken (); k = hie10 (lval); if (k == 0) { - /* Allow the & operator with an array */ + /* Allow the & operator with an array */ if (!IsArray (lval->e_tptr)) { Error (ERR_ILLEGAL_ADDRESS); } @@ -1495,11 +1495,11 @@ static int hie10 (struct expent* lval) } return 0; - case SIZEOF: - gettok (); + case TOK_SIZEOF: + NextToken (); if (istypeexpr ()) { type Type[MAXTYPELEN]; - gettok (); + NextToken (); lval->e_const = SizeOf (ParseType (Type)); ConsumeRParen (); } else { @@ -1524,11 +1524,11 @@ static int hie10 (struct expent* lval) k = hie11 (lval); switch (curtok) { - case INC: + case TOK_INC: post_incdec (lval, k, g_inc); return 0; - case DEC: + case TOK_DEC: post_incdec (lval, k, g_dec); return 0; @@ -1550,7 +1550,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */ CodeMark Mark1; CodeMark Mark2; GenDesc* Gen; - int tok; /* The operator token */ + token_t tok; /* The operator token */ unsigned ltype, type; int rconst; /* Operand is a constant */ @@ -1570,7 +1570,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */ /* Remember the operator token, then skip it */ tok = curtok; - gettok (); + NextToken (); /* Get the lhs on stack */ Mark1 = GetCodePos (); @@ -1619,9 +1619,9 @@ static int hie_internal (GenDesc** ops, /* List of generators */ /* Second value is constant - check for div */ type |= CF_CONST; rtype |= CF_CONST; - if (tok == DIV && lval2.e_const == 0) { + if (tok == TOK_DIV && lval2.e_const == 0) { Error (ERR_DIV_BY_ZERO); - } else if (tok == MOD && lval2.e_const == 0) { + } else if (tok == TOK_MOD && lval2.e_const == 0) { Error (ERR_MOD_BY_ZERO); } if ((Gen->Flags & GEN_NOPUSH) != 0) { @@ -1659,7 +1659,7 @@ static int hie_compare (GenDesc** ops, /* List of generators */ CodeMark Mark1; CodeMark Mark2; GenDesc* Gen; - int tok; /* The operator token */ + token_t tok; /* The operator token */ unsigned ltype; int rconst; /* Operand is a constant */ @@ -1670,7 +1670,7 @@ static int hie_compare (GenDesc** ops, /* List of generators */ /* Remember the operator token, then skip it */ tok = curtok; - gettok (); + NextToken (); /* Get the lhs on stack */ Mark1 = GetCodePos (); @@ -1800,7 +1800,7 @@ static void parseadd (int k, struct expent* lval) /* Skip the PLUS token */ - gettok (); + NextToken (); /* Get the left hand side type, initialize operation flags */ lhst = lval->e_tptr; @@ -1972,7 +1972,7 @@ static void parsesub (int k, struct expent* lval) /* Skip the MINUS token */ - gettok (); + NextToken (); /* Get the left hand side type, initialize operation flags */ lhst = lval->e_tptr; @@ -2126,9 +2126,9 @@ static int hie8 (struct expent* lval) /* Process + and - binary operators. */ { int k = hie9 (lval); - while (curtok == PLUS || curtok == MINUS) { + while (curtok == TOK_PLUS || curtok == TOK_MINUS) { - if (curtok == PLUS) { + if (curtok == TOK_PLUS) { parseadd (k, lval); } else { parsesub (k, lval); @@ -2222,7 +2222,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp) struct expent lval2; k = hie2 (lval); - if (curtok == DAMP) { + if (curtok == TOK_BOOL_AND) { /* Tell our caller that we're evaluating a boolean */ *BoolOp = 1; @@ -2242,10 +2242,10 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp) g_falsejump (CF_NONE, lab); /* Parse more boolean and's */ - while (curtok == DAMP) { + while (curtok == TOK_BOOL_AND) { /* Skip the && */ - gettok (); + NextToken (); /* Get rhs */ k = hie2 (&lval2); @@ -2255,7 +2255,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp) exprhs (CF_FORCECHAR, k, &lval2); /* Do short circuit evaluation */ - if (curtok == DAMP) { + if (curtok == TOK_BOOL_AND) { g_falsejump (CF_NONE, lab); } else { /* Last expression - will evaluate to true */ @@ -2293,7 +2293,7 @@ static int hieOr (struct expent *lval) k = hieAnd (lval, TrueLab, &BoolOp); /* Any boolean or's? */ - if (curtok == DBAR) { + if (curtok == TOK_BOOL_OR) { /* If the expr hasn't set condition codes, set the force-test flag */ if ((lval->e_test & E_CC) == 0) { @@ -2314,10 +2314,10 @@ static int hieOr (struct expent *lval) BoolOp = 1; /* while there's more expr */ - while (curtok == DBAR) { + while (curtok == TOK_BOOL_OR) { /* skip the || */ - gettok (); + NextToken (); /* Get a subexpr */ AndOp = 0; @@ -2333,7 +2333,7 @@ static int hieOr (struct expent *lval) */ #if 0 /* Seems this sometimes generates wrong code */ - if (curtok == DBAR && !AndOp) { + if (curtok == TOK_BOOL_OR && !AndOp) { g_truejump (CF_NONE, TrueLab); } #else @@ -2376,8 +2376,8 @@ static int hieQuest (struct expent *lval) k = hieOr (lval); - if (curtok == QUEST) { - gettok (); + if (curtok == TOK_QUEST) { + NextToken (); if ((lval->e_test & E_CC) == 0) { /* Condition codes not set, force a test */ lval->e_test |= E_FORCETEST; @@ -2481,7 +2481,7 @@ static void opeq (GenDesc* Gen, struct expent *lval, int k) CodeMark Mark; int MustScale; - gettok (); + NextToken (); if (k == 0) { Error (ERR_LVALUE_EXPECTED); return; @@ -2578,7 +2578,7 @@ static void addsubeq (GenDesc* Gen, struct expent *lval, int k) } /* Skip the operator */ - gettok (); + NextToken (); /* Check if we have a pointer expression and must scale rhs */ MustScale = (lval->e_tptr [0] == T_PTR); @@ -2609,14 +2609,14 @@ static void addsubeq (GenDesc* Gen, struct expent *lval, int k) if (lval->e_flags & E_MGLOBAL) { /* Static variable */ flags |= GlobalModeFlags (lval->e_flags); - if (Gen->Tok == PASGN) { + if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (flags, lval->e_name, lval->e_const, lval2.e_const); } else { g_subeqstatic (flags, lval->e_name, lval->e_const, lval2.e_const); } } else if (lval->e_flags & E_MLOCAL) { /* ref to localvar */ - if (Gen->Tok == PASGN) { + if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqlocal (flags, lval->e_const, lval2.e_const); } else { g_subeqlocal (flags, lval->e_const, lval2.e_const); @@ -2624,14 +2624,14 @@ static void addsubeq (GenDesc* Gen, struct expent *lval, int k) } else if (lval->e_flags & E_MCONST) { /* ref to absolute address */ flags |= CF_ABSOLUTE; - if (Gen->Tok == PASGN) { + if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (flags, lval->e_const, 0, lval2.e_const); } else { g_subeqstatic (flags, lval->e_const, 0, lval2.e_const); } } else if (lval->e_flags & E_MEXPR) { /* Address in a/x. */ - if (Gen->Tok == PASGN) { + if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqind (flags, lval->e_const, lval2.e_const); } else { g_subeqind (flags, lval->e_const, lval2.e_const); @@ -2726,12 +2726,12 @@ int hie1 (struct expent* lval) k = hieQuest (lval); switch (curtok) { - case RPAREN: - case SEMI: + case TOK_RPAREN: + case TOK_SEMI: return k; - case ASGN: - gettok (); + case TOK_ASSIGN: + NextToken (); if (k == 0) { Error (ERR_LVALUE_EXPECTED); } else { @@ -2739,43 +2739,43 @@ int hie1 (struct expent* lval) } break; - case PASGN: + case TOK_PLUS_ASSIGN: addsubeq (&GenPASGN, lval, k); break; - case SASGN: + case TOK_MINUS_ASSIGN: addsubeq (&GenSASGN, lval, k); break; - case MASGN: + case TOK_MUL_ASSIGN: opeq (&GenMASGN, lval, k); break; - case DASGN: + case TOK_DIV_ASSIGN: opeq (&GenDASGN, lval, k); break; - case MOASGN: + case TOK_MOD_ASSIGN: opeq (&GenMOASGN, lval, k); break; - case SLASGN: + case TOK_SHL_ASSIGN: opeq (&GenSLASGN, lval, k); break; - case SRASGN: + case TOK_SHR_ASSIGN: opeq (&GenSRASGN, lval, k); break; - case AASGN: + case TOK_AND_ASSIGN: opeq (&GenAASGN, lval, k); break; - case XOASGN: + case TOK_XOR_ASSIGN: opeq (&GenXOASGN, lval, k); break; - case OASGN: + case TOK_OR_ASSIGN: opeq (&GenOASGN, lval, k); break; @@ -2793,8 +2793,8 @@ int hie0 (struct expent *lval) int k; k = hie1 (lval); - while (curtok == COMMA) { - gettok (); + while (curtok == TOK_COMMA) { + NextToken (); k = hie1 (lval); } return k; @@ -2965,7 +2965,7 @@ void test (unsigned label, int cond) * compiler itself is one big hack...): If a semicolon follows, we * don't have a statement and may omit the jump. */ - if (curtok != SEMI) { + if (curtok != TOK_SEMI) { g_falsejump (CF_NONE, label); } } diff --git a/src/cc65/funcdesc.c b/src/cc65/funcdesc.c index 1a1ad262b..041c8045e 100644 --- a/src/cc65/funcdesc.c +++ b/src/cc65/funcdesc.c @@ -51,10 +51,9 @@ FuncDesc* NewFuncDesc (void) FuncDesc* F = xmalloc (sizeof (FuncDesc)); /* Nullify the fields */ - F->Flags = 0; + F->Flags = 0; F->SymTab = 0; - F->StructTab = 0; - F->EnumTab = 0; + F->TagTab = 0; F->ParamCount = 0; F->ParamSize = 0; diff --git a/src/cc65/funcdesc.h b/src/cc65/funcdesc.h index fddab0674..c18eb546c 100644 --- a/src/cc65/funcdesc.h +++ b/src/cc65/funcdesc.h @@ -45,21 +45,27 @@ /* Masks for the Flags field in FuncDesc */ -#define FD_IMPLICIT 0x0001U /* Implicitly declared function */ -#define FD_EMPTY 0x0002U /* Function with empty param list */ -#define FD_VOID_PARAM 0x0004U /* Function with a void param list */ +#define FD_IMPLICIT 0x0001U /* Implicitly declared function */ +#define FD_EMPTY 0x0002U /* Function with empty param list */ +#define FD_VOID_PARAM 0x0004U /* Function with a void param list */ #define FD_ELLIPSIS 0x0008U /* Function with variable param list */ -#define FD_FASTCALL 0x0010U /* __fastcall__ function */ +#define FD_FASTCALL 0x0010U /* __fastcall__ function */ +#define FD_OLDSTYLE 0x0020U /* Old style (K&R) function */ +#define FD_UNNAMED_PARAMS 0x0040U /* Function has unnamed params */ + +/* Bits that must be ignored when comparing funcs */ +#define FD_IGNORE (FD_IMPLICIT | FD_UNNAMED_PARAMS) + + /* Function descriptor */ typedef struct FuncDesc FuncDesc; struct FuncDesc { - unsigned Flags; /* Bitmapped flags FD_... */ - struct SymTable* SymTab; /* Symbol table */ - struct SymTable* StructTab; /* Struct table */ - struct SymTable* EnumTab; /* Enum table */ - unsigned ParamCount; /* Number of parameters */ - unsigned ParamSize; /* Size of the parameters */ + unsigned Flags; /* Bitmapped flags FD_... */ + struct SymTable* SymTab; /* Symbol table */ + struct SymTable* TagTab; /* Symbol table for structs/enums */ + unsigned ParamCount; /* Number of parameters */ + unsigned ParamSize; /* Size of the parameters */ }; diff --git a/src/cc65/function.c b/src/cc65/function.c index e8fe84575..4eeb39635 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -157,7 +157,7 @@ int AllocLocalSpace (Function* F, unsigned Size) /* Allocate space for the function locals, return stack offset */ { /* Add the size */ - F->LocalSize += Size; + F->LocalSize += Size; if (F->LocalSize > F->LocalMax) { F->LocalMax = F->LocalSize; } @@ -213,7 +213,7 @@ void NewFunc (SymEntry* Func) } /* Need a starting curly brace */ - if (curtok != LCURLY) { + if (curtok != TOK_LCURLY) { Error (ERR_LCURLY_EXPECTED); } diff --git a/src/cc65/goto.c b/src/cc65/goto.c index b18637012..5d6290004 100644 --- a/src/cc65/goto.c +++ b/src/cc65/goto.c @@ -51,10 +51,10 @@ void DoGoto (void) /* Process a goto statement. */ { /* Eat the "goto" */ - gettok (); + NextToken (); /* Label name must follow */ - if (curtok != IDENT) { + if (curtok != TOK_IDENT) { Error (ERR_IDENT_EXPECTED); @@ -68,7 +68,7 @@ void DoGoto (void) } /* Eat the label name */ - gettok (); + NextToken (); } @@ -83,8 +83,8 @@ void DoLabel (void) g_defloclabel (Entry->V.Label); /* Eat the ident and colon */ - gettok (); - gettok (); + NextToken (); + NextToken (); } diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 315194295..ec242c181 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -38,7 +38,7 @@ #include "codegen.h" #include "declare.h" #include "expr.h" -#include "function.h" /* ## */ +#include "function.h" #include "global.h" #include "mem.h" #include "symtab.h" @@ -131,10 +131,10 @@ static int AllocRegVar (const SymEntry* Sym, const type* tarray) void DeclareLocals (void) /* Declare local variables and types. */ { - int offs = oursp; /* Current stack offset for variable */ - int AutoSpace = 0; /* Unallocated space on the stack */ - int Size; /* Size of an auto variable */ - int Reg; /* Register variable offset */ + int offs = oursp; /* Current stack offset for variable */ + int AutoSpace = 0; /* Unallocated space on the stack */ + int Size; /* Size of an auto variable */ + int Reg; /* Register variable offset */ unsigned flags = 0; /* Code generator flags */ int SymbolSC; /* Storage class for symbol */ int ldata = 0; /* Local symbol data temp storage */ @@ -155,9 +155,10 @@ void DeclareLocals (void) } /* Accept type only declarations */ - if (curtok == SEMI) { - /* Type declaration only ### Check struct/union here */ - gettok (); + if (curtok == TOK_SEMI) { + /* Type declaration only */ + CheckEmptyDecl (&Spec); + NextToken (); continue; } @@ -205,12 +206,12 @@ void DeclareLocals (void) g_save_regvars (Reg, Size); /* Allow variable initialization */ - if (curtok == ASGN) { + if (curtok == TOK_ASSIGN) { struct expent lval; /* Skip the '=' */ - gettok (); + NextToken (); /* Get the expression into the primary */ expression1 (&lval); @@ -247,7 +248,7 @@ void DeclareLocals (void) /* Change SC in case it was register */ SymbolSC = (SymbolSC & ~SC_REGISTER) | SC_AUTO; - if (curtok == ASGN) { + if (curtok == TOK_ASSIGN) { struct expent lval; @@ -260,7 +261,7 @@ void DeclareLocals (void) AutoSpace = 0; /* Skip the '=' */ - gettok (); + NextToken (); /* Setup the type flags for the assignment */ flags = Size == 1? CF_FORCECHAR : CF_NONE; @@ -307,7 +308,7 @@ void DeclareLocals (void) g_res (Size); /* Allow assignments */ - if (curtok == ASGN) { + if (curtok == TOK_ASSIGN) { struct expent lval; @@ -315,7 +316,7 @@ void DeclareLocals (void) g_usecode (); /* Skip the '=' */ - gettok (); + NextToken (); /* Get the expression into the primary */ expression1 (&lval); @@ -340,7 +341,7 @@ void DeclareLocals (void) } else if ((SymbolSC & SC_STATIC) == SC_STATIC) { /* Static data */ - if (curtok == ASGN) { + if (curtok == TOK_ASSIGN) { /* Initialization ahead, switch to data segment */ g_usedata (); @@ -349,7 +350,7 @@ void DeclareLocals (void) g_defloclabel (ldata = GetLabel ()); /* Skip the '=' */ - gettok (); + NextToken (); /* Allow initialization of static vars */ ParseInit (Decl.Type); @@ -381,13 +382,13 @@ void DeclareLocals (void) /* Add the symbol to the symbol table */ AddLocalSym (Decl.Ident, Decl.Type, SymbolSC, ldata); - if (curtok != COMMA) { + if (curtok != TOK_COMMA) { break; } - gettok (); + NextToken (); } - if (curtok == SEMI) { - gettok (); + if (curtok == TOK_SEMI) { + NextToken (); } } @@ -466,5 +467,5 @@ void RestoreRegVars (int HaveResult) } } - + diff --git a/src/cc65/main.c b/src/cc65/main.c index 78090fd13..e86f65900 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -9,24 +9,15 @@ #include "../common/version.h" #include "asmcode.h" -#include "asmlabel.h" -#include "codegen.h" -#include "datatype.h" -#include "declare.h" +#include "compile.h" #include "error.h" -#include "expr.h" -#include "function.h" #include "global.h" #include "include.h" #include "io.h" -#include "litpool.h" #include "macrotab.h" #include "mem.h" #include "optimize.h" -#include "pragma.h" #include "scanner.h" -#include "stmt.h" -#include "symtab.h" @@ -54,7 +45,7 @@ static const char* TargetNames [] = { /*****************************************************************************/ -/* code */ +/* Code */ /*****************************************************************************/ @@ -252,259 +243,6 @@ static void DefineSym (const char* Def) -static void Parse (void) -/* Process all input text. - * At this level, only static declarations, defines, includes, and function - * definitions are legal.... - */ -{ - int comma; - SymEntry* Entry; - - kill (); - gettok (); /* "prime" the pump */ - gettok (); - while (curtok != CEOF) { - - DeclSpec Spec; - Declaration Decl; - int NeedStorage; - - /* Check for an ASM statement (which is allowed also on global level) */ - if (curtok == ASM) { - doasm (); - ConsumeSemi (); - continue; - } - - /* Check for a #pragma */ - if (curtok == PRAGMA) { - DoPragma (); - continue; - } - - /* Read variable defs and functions */ - 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; - } - - /* Check if this is only a type declaration */ - if (curtok == SEMI) { - gettok (); - 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; - - /* Read the next declaration */ - ParseDecl (&Spec, &Decl, DM_NEED_IDENT); - if (Decl.Ident[0] == '\0') { - gettok (); - break; - } - - /* Get the symbol flags */ - SymFlags = Spec.StorageClass; - if (IsFunc (Decl.Type)) { - SymFlags |= SC_FUNC; - } else { - if (NeedStorage) { - /* We will allocate storage, variable is defined */ - SymFlags |= SC_STORAGE | SC_DEF; - } - } - - /* Add an entry to the symbol table */ - Entry = AddGlobalSym (Decl.Ident, Decl.Type, SymFlags); - - /* Reserve storage for the variable if we need to */ - if (SymFlags & SC_STORAGE) { - - /* Get the size of the variable */ - unsigned Size = SizeOf (Decl.Type); - - /* Allow initialization */ - if (curtok == ASGN) { - - /* 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); - } - } - - /* Switch to the data segment */ - g_usedata (); - - /* Define a label */ - g_defgloblabel (Entry->Name); - - /* Skip the '=' */ - gettok (); - - /* Parse the initialization */ - ParseInit (Entry->Type); - } else { - - if (IsVoid (Decl.Type)) { - /* We cannot declare variables of type void */ - Error (ERR_ILLEGAL_TYPE); - } else if (Size == 0) { - /* Size is unknown */ - Error (ERR_UNKNOWN_SIZE); - } - - /* Switch to the BSS segment */ - g_usebss (); - - /* Define a label */ - g_defgloblabel (Entry->Name); - - /* Allocate space for uninitialized variable */ - g_res (SizeOf (Entry->Type)); - } - - } - - /* Check for end of declaration list */ - if (curtok == COMMA) { - gettok (); - comma = 1; - } else { - break; - } - } - - /* Function declaration? */ - if (IsFunc (Decl.Type)) { - - /* Function */ - if (!comma) { - - if (curtok == SEMI) { - - /* Prototype only */ - gettok (); - - } else { - if (Entry) { - NewFunc (Entry); - } - } - } - - } else { - - /* Must be followed by a semicolon */ - ConsumeSemi (); - - } - } -} - - - -static void Compile (void) -/* Compiler begins execution here. inp is input fd, output is output fd. */ -{ - char* Path; - - - /* Setup variables */ - filetab[0].f_iocb = inp; - 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); - } - - /* Add macros that are always defined */ - AddNumericMacro ("__CC65__", (VER_MAJOR * 0x100) + (VER_MINOR * 0x10) + VER_PATCH); - - /* Strict ANSI macro */ - if (ANSI) { - AddNumericMacro ("__STRICT_ANSI__", 1); - } - - /* Optimization macros */ - if (Optimize) { - AddNumericMacro ("__OPT__", 1); - if (FavourSize == 0) { - AddNumericMacro ("__OPT_i__", 1); - } - if (EnableRegVars) { - AddNumericMacro ("__OPT_r__", 1); - } - if (InlineStdFuncs) { - AddNumericMacro ("__OPT_s__", 1); - } - } - - /* Create the base lexical level */ - EnterGlobalLevel (); - - /* Generate the code generator preamble */ - g_preamble (); - - /* Ok, start the ball rolling... */ - Parse (); - - /* Dump literal pool. */ - DumpLiteralPool (); - - /* Write imported/exported symbols */ - EmitExternals (); - - if (Debug) { - PrintLiteralStats (stdout); - PrintMacroStats (stdout); - } - - /* Leave the main lexical level */ - LeaveGlobalLevel (); - - /* Print an error report */ - ErrorReport (); -} - - - int main (int argc, char **argv) { int i; diff --git a/src/cc65/make/gcc.mak b/src/cc65/make/gcc.mak index 9f4a75bcd..d30ffd444 100644 --- a/src/cc65/make/gcc.mak +++ b/src/cc65/make/gcc.mak @@ -15,6 +15,7 @@ OBJS = anonname.o \ asmline.o \ check.o \ codegen.o \ + compile.o \ ctrans.o \ datatype.o \ declare.o \ diff --git a/src/cc65/make/watcom.mak b/src/cc65/make/watcom.mak index b15123fab..a0d6625ea 100644 --- a/src/cc65/make/watcom.mak +++ b/src/cc65/make/watcom.mak @@ -69,6 +69,7 @@ OBJS = anonname.obj \ asmline.obj \ check.obj \ codegen.obj \ + compile.obj \ ctrans.obj \ datatype.obj \ declare.obj \ @@ -124,6 +125,7 @@ FILE asmlabel.obj FILE asmline.obj FILE check.obj FILE codegen.obj +FILE compile.obj FILE ctrans.obj FILE datatype.obj FILE declare.obj diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index b1fbc1f40..907ced7e9 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -79,7 +79,7 @@ enum { static void StringPragma (void (*Func) (const char*)) /* Handle a pragma that expects a string parameter */ { - if (curtok != SCONST) { + if (curtok != TOK_SCONST) { Error (ERR_STRLIT_EXPECTED); } else { /* Get the string */ @@ -93,7 +93,7 @@ static void StringPragma (void (*Func) (const char*)) } /* Skip the string (or error) token */ - gettok (); + NextToken (); } @@ -129,10 +129,10 @@ void DoPragma (void) int Pragma; /* Skip the token itself */ - gettok (); + NextToken (); /* Identifier must follow */ - if (curtok != IDENT) { + if (curtok != TOK_IDENT) { Error (ERR_IDENT_EXPECTED); return; } @@ -149,7 +149,7 @@ void DoPragma (void) } /* Skip the identifier and check for an open paren */ - gettok (); + NextToken (); ConsumeLParen (); /* Switch for the different pragmas */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 07ef3bd49..e30379371 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -401,7 +401,7 @@ static void addmac (void) static int Pass1 (char* from, char* to) /* Preprocessor pass 1. Remove whitespace and comments. */ { - int c; + int c; int done; ident Ident; int HaveParen; @@ -586,8 +586,8 @@ static int doiff (int skip) xlateline (); /* Prime the token pump (remove old tokens from the stream) */ - gettok (); - gettok (); + NextToken (); + NextToken (); /* Call the expression parser */ constexpr (&lval); diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 5ca35d4c7..27b6a15d1 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -48,44 +48,45 @@ static struct Keyword { unsigned char Tok; /* The token */ unsigned char Type; /* Token type */ } Keywords [] = { - { "__AX__", AX, TT_C }, - { "__EAX__", EAX, TT_C }, - { "__asm__", ASM, TT_C }, - { "__fastcall__", FASTCALL, TT_C }, - { "asm", ASM, TT_EXT }, - { "auto", AUTO, TT_C }, - { "break", BREAK, TT_C }, - { "case", CASE, TT_C }, - { "char", CHAR, TT_C }, - { "const", CONST, TT_C }, - { "continue", CONTINUE, TT_C }, - { "default", DEFAULT, TT_C }, - { "do", DO, TT_C }, - { "double", DOUBLE, TT_C }, - { "else", ELSE, TT_C }, - { "enum", ENUM, TT_C }, - { "extern", EXTERN, TT_C }, - { "fastcall", FASTCALL, TT_EXT }, - { "float", FLOAT, TT_C }, - { "for", FOR, TT_C }, - { "goto", GOTO, TT_C }, - { "if", IF, TT_C }, - { "int", INT, TT_C }, - { "long", LONG, TT_C }, - { "register", REGISTER, TT_C }, - { "return", RETURN, TT_C }, - { "short", SHORT, TT_C }, - { "signed", SIGNED, TT_C }, - { "sizeof", SIZEOF, TT_C }, - { "static", STATIC, TT_C }, - { "struct", STRUCT, TT_C }, - { "switch", SWITCH, TT_C }, - { "typedef", TYPEDEF, TT_C }, - { "union", UNION, TT_C }, - { "unsigned", UNSIGNED, TT_C }, - { "void", VOID, TT_C }, - { "volatile", VOLATILE, TT_C }, - { "while", WHILE, TT_C }, + { "__AX__", TOK_AX, TT_C }, + { "__EAX__", TOK_EAX, TT_C }, + { "__asm__", TOK_ASM, TT_C }, + { "__attribute__", TOK_ATTRIBUTE, TT_C }, + { "__fastcall__", TOK_FASTCALL, TT_C }, + { "asm", TOK_ASM, TT_EXT }, + { "auto", TOK_AUTO, TT_C }, + { "break", TOK_BREAK, TT_C }, + { "case", TOK_CASE, TT_C }, + { "char", TOK_CHAR, TT_C }, + { "const", TOK_CONST, TT_C }, + { "continue", TOK_CONTINUE, TT_C }, + { "default", TOK_DEFAULT, TT_C }, + { "do", TOK_DO, TT_C }, + { "double", TOK_DOUBLE, TT_C }, + { "else", TOK_ELSE, TT_C }, + { "enum", TOK_ENUM, TT_C }, + { "extern", TOK_EXTERN, TT_C }, + { "fastcall", TOK_FASTCALL, TT_EXT }, + { "float", TOK_FLOAT, TT_C }, + { "for", TOK_FOR, TT_C }, + { "goto", TOK_GOTO, TT_C }, + { "if", TOK_IF, TT_C }, + { "int", TOK_INT, TT_C }, + { "long", TOK_LONG, TT_C }, + { "register", TOK_REGISTER, TT_C }, + { "return", TOK_RETURN, TT_C }, + { "short", TOK_SHORT, TT_C }, + { "signed", TOK_SIGNED, TT_C }, + { "sizeof", TOK_SIZEOF, TT_C }, + { "static", TOK_STATIC, TT_C }, + { "struct", TOK_STRUCT, TT_C }, + { "switch", TOK_SWITCH, TT_C }, + { "typedef", TOK_TYPEDEF, TT_C }, + { "union", TOK_UNION, TT_C }, + { "unsigned", TOK_UNSIGNED, TT_C }, + { "void", TOK_VOID, TT_C }, + { "volatile", TOK_VOLATILE, TT_C }, + { "while", TOK_WHILE, TT_C }, }; #define KEY_COUNT (sizeof (Keywords) / sizeof (Keywords [0])) @@ -123,7 +124,7 @@ static int FindKey (char* Key) if (K && (K->Type != TT_EXT || ANSI == 0)) { return K->Tok; } else { - return IDENT; + return TOK_IDENT; } } @@ -303,7 +304,7 @@ static void CharConst (void) } /* Setup values and attributes */ - nxttok = CCONST; + nxttok = TOK_CCONST; nxtval = SignExtendChar (ctrans (c)); /* Translate into target charset */ nxttype = type_int; /* Character constants have type int */ } @@ -314,7 +315,7 @@ static void StringConst (void) /* Parse a quoted string */ { nxtval = GetLiteralOffs (); - nxttok = SCONST; + nxttok = TOK_SCONST; /* Be sure to concatenate strings */ while (*lptr == '\"') { @@ -344,7 +345,7 @@ static void StringConst (void) -void gettok (void) +void NextToken (void) /* Get next token from input stream */ { char c; @@ -359,7 +360,7 @@ void gettok (void) /* Skip spaces and read the next line if needed */ if (skipwhite () == 0) { /* End of file reached */ - nxttok = CEOF; + nxttok = TOK_CEOF; return; } @@ -460,14 +461,14 @@ void gettok (void) /* Set the value and the token */ nxtval = k; - nxttok = ICONST; + nxttok = TOK_ICONST; return; } if (issym (token)) { /* Check for a keyword */ - if ((nxttok = FindKey (token)) != IDENT) { + if ((nxttok = FindKey (token)) != TOK_IDENT) { /* Reserved word found */ return; } @@ -476,15 +477,15 @@ void gettok (void) /* Special symbols */ if (strcmp (token, "__FILE__") == 0) { nxtval = AddLiteral (fin); - nxttok = SCONST; + nxttok = TOK_SCONST; return; } else if (strcmp (token, "__LINE__") == 0) { - nxttok = ICONST; + nxttok = TOK_ICONST; nxtval = ln; nxttype = type_int; return; } else if (strcmp (token, "__fixargs__") == 0) { - nxttok = ICONST; + nxttok = TOK_ICONST; nxtval = GetParamSize (CurrentFunc); nxttype = type_uint; return; @@ -492,7 +493,7 @@ void gettok (void) /* __func__ is only defined in functions */ if (CurrentFunc) { nxtval = AddLiteral (GetFuncName (CurrentFunc)); - nxttok = SCONST; + nxttok = TOK_SCONST; return; } } @@ -500,7 +501,7 @@ void gettok (void) /* No reserved word but identifier */ strcpy (NextTok.Ident, token); - NextTok.Tok = IDENT; + NextTok.Tok = TOK_IDENT; return; } @@ -509,9 +510,9 @@ void gettok (void) case '!': if (*++lptr == '=') { - SetTok (NE); + SetTok (TOK_NE); } else { - nxttok = BANG; + nxttok = TOK_BOOL_NOT; } break; @@ -521,22 +522,22 @@ void gettok (void) case '%': if (*++lptr == '=') { - SetTok (MOASGN); + SetTok (TOK_MOD_ASSIGN); } else { - nxttok = MOD; + nxttok = TOK_MOD; } break; case '&': switch (*++lptr) { case '&': - SetTok (DAMP); + SetTok (TOK_BOOL_AND); break; case '=': - SetTok (AASGN); + SetTok (TOK_AND_ASSIGN); break; default: - nxttok = AMP; + nxttok = TOK_AND; } break; @@ -545,167 +546,167 @@ void gettok (void) break; case '(': - SetTok (LPAREN); + SetTok (TOK_LPAREN); break; case ')': - SetTok (RPAREN); + SetTok (TOK_RPAREN); break; case '*': if (*++lptr == '=') { - SetTok (MASGN); + SetTok (TOK_MUL_ASSIGN); } else { - nxttok = STAR; + nxttok = TOK_STAR; } break; case '+': switch (*++lptr) { case '+': - SetTok (INC); + SetTok (TOK_INC); break; case '=': - SetTok (PASGN); + SetTok (TOK_PLUS_ASSIGN); break; default: - nxttok = PLUS; + nxttok = TOK_PLUS; } break; case ',': - SetTok (COMMA); + SetTok (TOK_COMMA); break; case '-': switch (*++lptr) { case '-': - SetTok (DEC); + SetTok (TOK_DEC); break; case '=': - SetTok (SASGN); + SetTok (TOK_MINUS_ASSIGN); break; case '>': - SetTok (PREF); + SetTok (TOK_PTR_REF); break; default: - nxttok = MINUS; + nxttok = TOK_MINUS; } break; case '.': if (*++lptr == '.') { if (*++lptr == '.') { - SetTok (ELLIPSIS); + SetTok (TOK_ELLIPSIS); } else { unknown (*lptr); } } else { - nxttok = DOT; + nxttok = TOK_DOT; } break; case '/': if (*++lptr == '=') { - SetTok (DASGN); + SetTok (TOK_DIV_ASSIGN); } else { - nxttok = DIV; + nxttok = TOK_DIV; } break; case ':': - SetTok (COLON); + SetTok (TOK_COLON); break; case ';': - SetTok (SEMI); + SetTok (TOK_SEMI); break; case '<': switch (*++lptr) { case '=': - SetTok (LE); + SetTok (TOK_LE); break; case '<': if (*++lptr == '=') { - SetTok (SLASGN); + SetTok (TOK_SHL_ASSIGN); } else { - nxttok = ASL; + nxttok = TOK_SHL; } break; default: - nxttok = LT; + nxttok = TOK_LT; } break; case '=': if (*++lptr == '=') { - SetTok (EQ); + SetTok (TOK_EQ); } else { - nxttok = ASGN; + nxttok = TOK_ASSIGN; } break; case '>': switch (*++lptr) { case '=': - SetTok (GE); + SetTok (TOK_GE); break; case '>': if (*++lptr == '=') { - SetTok (SRASGN); + SetTok (TOK_SHR_ASSIGN); } else { - nxttok = ASR; + nxttok = TOK_SHR; } break; default: - nxttok = GT; + nxttok = TOK_GT; } break; case '?': - SetTok (QUEST); + SetTok (TOK_QUEST); break; case '[': - SetTok (LBRACK); + SetTok (TOK_LBRACK); break; case ']': - SetTok (RBRACK); + SetTok (TOK_RBRACK); break; case '^': if (*++lptr == '=') { - SetTok (XOASGN); + SetTok (TOK_XOR_ASSIGN); } else { - nxttok = XOR; + nxttok = TOK_XOR; } break; case '{': - SetTok (LCURLY); + SetTok (TOK_LCURLY); break; case '|': switch (*++lptr) { case '|': - SetTok (DBAR); + SetTok (TOK_BOOL_OR); break; case '=': - SetTok (OASGN); + SetTok (TOK_OR_ASSIGN); break; default: - nxttok = BAR; + nxttok = TOK_OR; } break; case '}': - SetTok (RCURLY); + SetTok (TOK_RCURLY); break; case '~': - SetTok (COMP); + SetTok (TOK_COMP); break; case '#': @@ -714,7 +715,7 @@ void gettok (void) /* OOPS - should not happen */ Error (ERR_CPP_DIRECTIVE_EXPECTED); } - nxttok = PRAGMA; + nxttok = TOK_PRAGMA; break; default: @@ -726,13 +727,13 @@ void gettok (void) -void Consume (unsigned Token, unsigned char ErrNum) +void Consume (token_t Token, unsigned ErrNum) /* Eat token if it is the next in the input stream, otherwise print an error * message. */ { if (curtok == Token) { - gettok (); + NextToken (); } else { Error (ErrNum); } @@ -743,7 +744,7 @@ void Consume (unsigned Token, unsigned char ErrNum) void ConsumeColon (void) /* Check for a colon and skip it. */ { - Consume (COLON, ERR_COLON_EXPECTED); + Consume (TOK_COLON, ERR_COLON_EXPECTED); } @@ -752,12 +753,12 @@ void ConsumeSemi (void) /* Check for a semicolon and skip it. */ { /* Try do be smart about typos... */ - if (curtok == SEMI) { - gettok (); + if (curtok == TOK_SEMI) { + NextToken (); } else { Error (ERR_SEMICOLON_EXPECTED); - if (curtok == COLON || curtok == COMMA) { - gettok (); + if (curtok == TOK_COLON || curtok == TOK_COMMA) { + NextToken (); } } } @@ -767,7 +768,7 @@ void ConsumeSemi (void) void ConsumeLParen (void) /* Check for a left parenthesis and skip it */ { - Consume (LPAREN, ERR_LPAREN_EXPECTED); + Consume (TOK_LPAREN, ERR_LPAREN_EXPECTED); } @@ -775,7 +776,7 @@ void ConsumeLParen (void) void ConsumeRParen (void) /* Check for a right parenthesis and skip it */ { - Consume (RPAREN, ERR_RPAREN_EXPECTED); + Consume (TOK_RPAREN, ERR_RPAREN_EXPECTED); } @@ -783,7 +784,7 @@ void ConsumeRParen (void) void ConsumeLBrack (void) /* Check for a left bracket and skip it */ { - Consume (LBRACK, ERR_LBRACK_EXPECTED); + Consume (TOK_LBRACK, ERR_LBRACK_EXPECTED); } @@ -791,7 +792,7 @@ void ConsumeLBrack (void) void ConsumeRBrack (void) /* Check for a right bracket and skip it */ { - Consume (RBRACK, ERR_RBRACK_EXPECTED); + Consume (TOK_RBRACK, ERR_RBRACK_EXPECTED); } @@ -799,7 +800,7 @@ void ConsumeRBrack (void) void ConsumeLCurly (void) /* Check for a left curly brace and skip it */ { - Consume (LCURLY, ERR_LCURLY_EXPECTED); + Consume (TOK_LCURLY, ERR_LCURLY_EXPECTED); } @@ -807,7 +808,7 @@ void ConsumeLCurly (void) void ConsumeRCurly (void) /* Check for a right curly brace and skip it */ { - Consume (RCURLY, ERR_RCURLY_EXPECTED); + Consume (TOK_RCURLY, ERR_RCURLY_EXPECTED); } diff --git a/src/cc65/scanner.h b/src/cc65/scanner.h index 3becee72f..5653d953a 100644 --- a/src/cc65/scanner.h +++ b/src/cc65/scanner.h @@ -17,115 +17,120 @@ /*****************************************************************************/ -/* token definitions */ +/* Token definitions */ /*****************************************************************************/ -#define CEOF 0 - -#define AUTO 10 -#define EXTERN 11 -#define REGISTER 12 -#define STATIC 13 -#define TYPEDEF 14 -#define ENUM 15 -#define CONST 16 -#define VOLATILE 17 - -#define FIRSTTYPE 19 -#define CHAR 19 -#define INT 20 -#define DOUBLE 21 -#define FLOAT 22 -#define LONG 23 -#define UNSIGNED 24 -#define SIGNED 25 -#define SHORT 26 -#define STRUCT 27 -#define UNION 28 -#define VOID 29 -#define LASTTYPE 29 - -#define DO 30 -#define FOR 31 -#define GOTO 32 -#define IF 33 -#define RETURN 34 -#define SWITCH 35 -#define WHILE 36 - -#define ASM 40 -#define CASE 41 -#define DEFAULT 42 -#define BREAK 43 -#define CONTINUE 44 -#define ELSE 45 -#define ELLIPSIS 46 -#define SIZEOF 47 - -#define IDENT 50 -#define SEMI 51 - -/* primary operators */ -#define LBRACK 52 -#define LPAREN 53 -#define DOT 54 -#define PREF 55 - -#define LCURLY 56 -#define RBRACK 57 -#define COMP 58 -#define INC 59 -#define PASGN 60 -#define PLUS 61 -#define COMMA 62 -#define DEC 63 -#define SASGN 64 -#define RCURLY 65 -#define MINUS 66 -#define MASGN 67 -#define STAR 68 -#define DASGN 69 -#define DIV 70 -#define DAMP 71 -#define AASGN 72 -#define AMP 73 -#define NE 74 -#define BANG 75 -#define DBAR 76 -#define OASGN 77 -#define BAR 78 -#define EQ 79 -#define ASGN 80 -#define SLASGN 81 -#define ASL 82 - -/* inequalities */ -#define LE 83 -#define LT 84 -#define GE 85 -#define GT 86 - -#define SRASGN 87 -#define ASR 88 -#define XOASGN 89 -#define XOR 90 -#define MOASGN 91 -#define MOD 92 -#define QUEST 93 -#define COLON 94 -#define RPAREN 95 -#define SCONST 96 -#define ICONST 97 -#define CCONST 98 -#define FCONST 99 - -#define FASTCALL 100 -#define AX 101 -#define EAX 102 - -#define PRAGMA 110 +typedef enum token_t { + TOK_CEOF, + + TOK_AUTO, + TOK_EXTERN, + TOK_REGISTER, + TOK_STATIC, + TOK_TYPEDEF, + TOK_ENUM, + TOK_CONST, + TOK_VOLATILE, + + /* Tokens denoting types */ + TOK_FIRSTTYPE, + TOK_CHAR = TOK_FIRSTTYPE, + TOK_INT, + TOK_DOUBLE, + TOK_FLOAT, + TOK_LONG, + TOK_UNSIGNED, + TOK_SIGNED, + TOK_SHORT, + TOK_STRUCT, + TOK_UNION, + TOK_VOID, + TOK_LASTTYPE = TOK_VOID, + + /* Control statements */ + TOK_DO, + TOK_FOR, + TOK_GOTO, + TOK_IF, + TOK_RETURN, + TOK_SWITCH, + TOK_WHILE, + + TOK_ASM, + TOK_CASE, + TOK_DEFAULT, + TOK_BREAK, + TOK_CONTINUE, + TOK_ELSE, + TOK_ELLIPSIS, + TOK_SIZEOF, + + TOK_IDENT, + TOK_SEMI, + + /* Primary operators */ + TOK_LBRACK, + TOK_LPAREN, + TOK_DOT, + TOK_PTR_REF, + + TOK_LCURLY, + TOK_RBRACK, + TOK_COMP, + TOK_INC, + TOK_PLUS_ASSIGN, + TOK_PLUS, + TOK_COMMA, + TOK_DEC, + TOK_MINUS_ASSIGN, + TOK_RCURLY, + TOK_MINUS, + TOK_MUL_ASSIGN, + TOK_STAR, + TOK_DIV_ASSIGN, + TOK_DIV, + TOK_BOOL_AND, + TOK_AND_ASSIGN, + TOK_AND, + TOK_NE, + TOK_BOOL_NOT, + TOK_BOOL_OR, + TOK_OR_ASSIGN, + TOK_OR, + TOK_EQ, + TOK_ASSIGN, + TOK_SHL_ASSIGN, + TOK_SHL, + + /* Inequalities */ + TOK_LE, + TOK_LT, + TOK_GE, + TOK_GT, + + TOK_SHR_ASSIGN, + TOK_SHR, + TOK_XOR_ASSIGN, + TOK_XOR, + TOK_MOD_ASSIGN, + TOK_MOD, + TOK_QUEST, + TOK_COLON, + TOK_RPAREN, + TOK_SCONST, + TOK_ICONST, + TOK_CCONST, + TOK_FCONST, + + TOK_ATTRIBUTE, + TOK_FASTCALL, + TOK_AX, + TOK_EAX, + + TOK_PRAGMA +} token_t; @@ -138,7 +143,7 @@ /* Token stuff */ typedef struct Token_ Token; struct Token_ { - unsigned Tok; /* The token itself */ + token_t Tok; /* The token itself */ long IVal; /* The integer attribute */ ident Ident; /* Identifier if IDENT */ unsigned Pos; /* Source line where the token comes from */ @@ -173,10 +178,10 @@ void symname (char* s); int issym (char* s); /* Get symbol from input stream or return 0 if not a symbol. */ -void gettok (void); +void NextToken (void); /* Get next token from input stream */ -void Consume (unsigned Token, unsigned char ErrNum); +void Consume (token_t Token, unsigned ErrNum); /* Eat token if it is the next in the input stream, otherwise print an error * message. */ diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index d6560463a..51a6009e3 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -61,7 +61,7 @@ static int doif (void) int gotbreak; /* Skip the if */ - gettok (); + NextToken (); /* Generate a jump label and parse the condition */ flab1 = GetLabel (); @@ -71,7 +71,7 @@ static int doif (void) gotbreak = statement (); /* Else clause present? */ - if (curtok != ELSE) { + if (curtok != TOK_ELSE) { g_defloclabel (flab1); /* Since there's no else clause, we're not sure, if the a break @@ -82,7 +82,7 @@ static int doif (void) } else { /* Skip the else */ - gettok (); + NextToken (); /* If we had some sort of break statement at the end of the if clause, * there's no need to generate an additional jump around the else @@ -116,7 +116,7 @@ static void dowhile (char wtype) int loop; int lab; - gettok (); + NextToken (); loop = GetLabel (); lab = GetLabel (); addloop (oursp, loop, lab, 0, 0); @@ -132,9 +132,9 @@ static void dowhile (char wtype) * do another small optimization here, and use a conditional jump * instead an absolute one. */ - if (curtok == SEMI) { + if (curtok == TOK_SEMI) { /* Shortcut */ - gettok (); + NextToken (); /* Use a conditional jump */ g_truejump (CF_NONE, loop); } else { @@ -148,7 +148,7 @@ static void dowhile (char wtype) /* Do loop */ statement (); - Consume (WHILE, ERR_WHILE_EXPECTED); + Consume (TOK_WHILE, ERR_WHILE_EXPECTED); test (loop, 1); ConsumeSemi (); g_defloclabel (lab); @@ -167,8 +167,8 @@ static void doreturn (void) int HaveVal = 0; /* Do we have a return value in ax? */ - gettok (); - if (curtok != SEMI) { + NextToken (); + if (curtok != TOK_SEMI) { if (HasVoidReturn (CurrentFunc)) { Error (ERR_CANNOT_RETURN_VALUE); } @@ -198,7 +198,7 @@ static void dobreak (void) { struct loopdesc* l; - gettok (); + NextToken (); if ((l = currentloop ()) == 0) { /* Error: No current loop */ return; @@ -214,7 +214,7 @@ static void docontinue (void) { struct loopdesc* l; - gettok (); + NextToken (); if ((l = currentloop ()) == 0) { /* Error: Not in loop */ return; @@ -263,9 +263,9 @@ static void cascadeswitch (struct expent* eval) /* Parse the labels */ lcount = 0; - while (curtok != RCURLY) { + while (curtok != TOK_RCURLY) { - if (curtok == CASE || curtok == DEFAULT) { + if (curtok == TOK_CASE || curtok == TOK_DEFAULT) { /* If the code for the previous selector did not end with a * break statement, we must jump over the next selector test. @@ -284,16 +284,16 @@ static void cascadeswitch (struct expent* eval) nextlab = 0; } - while (curtok == CASE || curtok == DEFAULT) { + while (curtok == TOK_CASE || curtok == TOK_DEFAULT) { /* Parse the selector */ - if (curtok == CASE) { + if (curtok == TOK_CASE) { /* Count labels */ ++lcount; /* Skip the "case" token */ - gettok (); + NextToken (); /* Read the selector expression */ constexpr (&lval); @@ -343,13 +343,13 @@ static void cascadeswitch (struct expent* eval) /* If another case follows, we will jump to the code if * the condition is true. */ - if (curtok == CASE) { + if (curtok == TOK_CASE) { /* Create a code label if needed */ if (codelab == 0) { codelab = GetLabel (); } g_falsejump (CF_NONE, codelab); - } else if (curtok != DEFAULT) { + } else if (curtok != TOK_DEFAULT) { /* No case follows, jump to next selector */ if (nextlab == 0) { nextlab = GetLabel (); @@ -360,13 +360,13 @@ static void cascadeswitch (struct expent* eval) } else { /* Default case */ - gettok (); + NextToken (); /* Skip the colon */ ConsumeColon (); /* Handle the pathologic case: DEFAULT followed by CASE */ - if (curtok == CASE) { + if (curtok == TOK_CASE) { if (codelab == 0) { codelab = GetLabel (); } @@ -385,7 +385,7 @@ static void cascadeswitch (struct expent* eval) } /* Parse statements */ - if (curtok != RCURLY) { + if (curtok != TOK_RCURLY) { havebreak = statement (); } } @@ -396,7 +396,7 @@ static void cascadeswitch (struct expent* eval) } /* Eat the closing curly brace */ - gettok (); + NextToken (); /* Define the exit label and, if there's a next label left, create this * one, too. @@ -445,15 +445,15 @@ static void tableswitch (struct expent* eval) /* Jump behind the code for the CASE labels */ g_jump (lcase = GetLabel ()); lcount = 0; - while (curtok != RCURLY) { - if (curtok == CASE || curtok == DEFAULT) { + while (curtok != TOK_RCURLY) { + if (curtok == TOK_CASE || curtok == TOK_DEFAULT) { if (lcount >= CASE_MAX) { Fatal (FAT_TOO_MANY_CASE_LABELS); } label = GetLabel (); do { - if (curtok == CASE) { - gettok (); + if (curtok == TOK_CASE) { + NextToken (); constexpr (&lval); if (!IsInt (lval.e_tptr)) { Error (ERR_ILLEGAL_TYPE); @@ -463,15 +463,15 @@ static void tableswitch (struct expent* eval) ++p; ++lcount; } else { - gettok (); + NextToken (); dlabel = label; } ConsumeColon (); - } while (curtok == CASE || curtok == DEFAULT); + } while (curtok == TOK_CASE || curtok == TOK_DEFAULT); g_defloclabel (label); havebreak = 0; } - if (curtok != RCURLY) { + if (curtok != TOK_RCURLY) { havebreak = statement (); } } @@ -482,7 +482,7 @@ static void tableswitch (struct expent* eval) } /* Eat the closing curly brace */ - gettok (); + NextToken (); /* If the last statement doesn't have a break or return, add one */ if (!havebreak) { @@ -526,7 +526,7 @@ static void doswitch (void) struct expent eval; /* Switch statement expression */ /* Eat the "switch" */ - gettok (); + NextToken (); /* Read the switch expression */ ConsumeLParen (); @@ -557,19 +557,19 @@ static void dofor (void) struct expent lval2; struct expent lval3; - gettok (); + NextToken (); loop = GetLabel (); lab = GetLabel (); linc = GetLabel (); lstat = GetLabel (); addloop (oursp, loop, lab, linc, lstat); ConsumeLParen (); - if (curtok != SEMI) { /* exp1 */ + if (curtok != TOK_SEMI) { /* exp1 */ expression (&lval1); } ConsumeSemi (); g_defloclabel (loop); - if (curtok != SEMI) { /* exp2 */ + if (curtok != TOK_SEMI) { /* exp2 */ boolexpr (&lval2); g_truejump (CF_NONE, lstat); g_jump (lab); @@ -578,7 +578,7 @@ static void dofor (void) } ConsumeSemi (); g_defloclabel (linc); - if (curtok != RPAREN) { /* exp3 */ + if (curtok != TOK_RPAREN) { /* exp3 */ expression (&lval3); } ConsumeRParen (); @@ -601,7 +601,7 @@ static int statement (void) struct expent lval; /* */ - if (curtok == IDENT && nxttok == COLON) { + if (curtok == TOK_IDENT && nxttok == TOK_COLON) { /* Special handling for a label */ DoLabel (); @@ -610,54 +610,54 @@ static int statement (void) switch (curtok) { - case LCURLY: + case TOK_LCURLY: return compound (); - case IF: + case TOK_IF: return doif (); - case WHILE: + case TOK_WHILE: dowhile ('w'); break; - case DO: + case TOK_DO: dowhile ('d'); break; - case SWITCH: + case TOK_SWITCH: doswitch (); break; - case RETURN: + case TOK_RETURN: doreturn (); ConsumeSemi (); return 1; - case BREAK: + case TOK_BREAK: dobreak (); ConsumeSemi (); return 1; - case CONTINUE: + case TOK_CONTINUE: docontinue (); ConsumeSemi (); return 1; - case FOR: + case TOK_FOR: dofor (); break; - case GOTO: + case TOK_GOTO: DoGoto (); ConsumeSemi (); return 1; - case SEMI: + case TOK_SEMI: /* ignore it. */ - gettok (); + NextToken (); break; - case PRAGMA: + case TOK_PRAGMA: DoPragma (); break; @@ -682,7 +682,7 @@ int compound (void) int oldsp; /* eat LCURLY */ - gettok (); + NextToken (); /* Remember the stack at block entry */ oldsp = oursp; @@ -698,8 +698,8 @@ int compound (void) /* Now process statements in the function body */ isbrk = 0; - while (curtok != RCURLY) { - if (curtok == CEOF) + while (curtok != TOK_RCURLY) { + if (curtok == TOK_CEOF) break; else { isbrk = statement (); diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index f5ccf6a51..077a81a89 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -37,7 +37,7 @@ #include #include #include - + #include "../common/hashstr.h" #include "asmcode.h" @@ -86,10 +86,8 @@ SymTable EmptySymTab = { static unsigned LexicalLevel = 0; /* For safety checks */ static SymTable* SymTab0 = 0; static SymTable* SymTab = 0; -static SymTable* StructTab0 = 0; -static SymTable* StructTab = 0; -static SymTable* EnumTab0 = 0; -static SymTable* EnumTab = 0; +static SymTable* TagTab0 = 0; +static SymTable* TagTab = 0; static SymTable* LabelTab = 0; @@ -207,11 +205,8 @@ void EnterGlobalLevel (void) /* Create and assign the symbol table */ SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL); - /* Create and assign the struct table */ - StructTab0 = StructTab = NewSymTable (SYMTAB_SIZE_GLOBAL); - - /* Create and assign the enum table */ - EnumTab0 = EnumTab = NewSymTable (SYMTAB_SIZE_GLOBAL); + /* Create and assign the tag table */ + TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL); } @@ -228,14 +223,12 @@ void LeaveGlobalLevel (void) /* Dump the tables if requested */ if (Debug) { PrintSymTable (SymTab0, stdout, "Global symbol table"); - PrintSymTable (StructTab0, stdout, "Global struct table"); - PrintSymTable (EnumTab0, stdout, "Global enum table"); + PrintSymTable (TagTab0, stdout, "Global tag table"); } /* Don't delete the symbol and struct tables! */ - SymTab0 = SymTab = 0; - StructTab0 = StructTab = 0; - EnumTab0 = EnumTab = 0; + SymTab0 = SymTab = 0; + TagTab0 = TagTab = 0; } @@ -253,15 +246,10 @@ void EnterFunctionLevel (void) S->PrevTab = SymTab; SymTab = S; - /* Get a new struct table and make it current */ - S = NewSymTable (SYMTAB_SIZE_FUNCTION); - S->PrevTab = StructTab; - StructTab = S; - - /* Get a new enum table and make it current */ + /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_FUNCTION); - S->PrevTab = EnumTab; - EnumTab = S; + S->PrevTab = TagTab; + TagTab = S; /* Create and assign a new label table */ LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); @@ -276,14 +264,12 @@ void RememberFunctionLevel (struct FuncDesc* F) --LexicalLevel; /* Remember the tables */ - F->SymTab = SymTab; - F->StructTab = StructTab; - F->EnumTab = EnumTab; + F->SymTab = SymTab; + F->TagTab = TagTab; /* Don't delete the tables */ - SymTab = SymTab->PrevTab; - StructTab = StructTab->PrevTab; - EnumTab = EnumTab->PrevTab; + SymTab = SymTab->PrevTab; + TagTab = TagTab->PrevTab; } @@ -298,11 +284,8 @@ void ReenterFunctionLevel (struct FuncDesc* F) F->SymTab->PrevTab = SymTab; SymTab = F->SymTab; - F->StructTab->PrevTab = StructTab; - StructTab = F->StructTab; - - F->EnumTab->PrevTab = EnumTab; - EnumTab = F->EnumTab; + F->TagTab->PrevTab = TagTab; + TagTab = F->TagTab; /* Create and assign a new label table */ LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); @@ -326,9 +309,8 @@ void LeaveFunctionLevel (void) } /* Don't delete the tables */ - SymTab = SymTab->PrevTab; - StructTab = StructTab->PrevTab; - EnumTab = EnumTab->PrevTab; + SymTab = SymTab->PrevTab; + TagTab = TagTab->PrevTab; LabelTab = 0; } @@ -347,15 +329,10 @@ void EnterBlockLevel (void) S->PrevTab = SymTab; SymTab = S; - /* Get a new struct table and make it current */ - S = NewSymTable (SYMTAB_SIZE_BLOCK); - S->PrevTab = StructTab; - StructTab = S; - - /* Get a new enum table and make it current */ + /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); - S->PrevTab = EnumTab; - EnumTab = S; + S->PrevTab = TagTab; + TagTab = S; } @@ -370,9 +347,8 @@ void LeaveBlockLevel (void) CheckSymTable (SymTab); /* Don't delete the tables */ - SymTab = SymTab->PrevTab; - StructTab = StructTab->PrevTab; - EnumTab = EnumTab->PrevTab; + SymTab = SymTab->PrevTab; + TagTab = TagTab->PrevTab; } @@ -463,18 +439,18 @@ SymEntry* FindSym (const char* Name) -SymEntry* FindStructSym (const char* Name) -/* Find the symbol with the given name in the struct table */ +SymEntry* FindLocalSym (const char* Name) +/* Find the symbol with the given name in the current symbol table only */ { - return FindSymInTree (StructTab, Name); + return FindSymInTable (SymTab, Name, HashStr (Name)); } -SymEntry* FindEnumSym (const char* Name) -/* Find the symbol with the given name in the enum table */ +SymEntry* FindTagSym (const char* Name) +/* Find the symbol with the given name in the tag table */ { - return FindSymInTree (EnumTab, Name); + return FindSymInTree (TagTab, Name); } @@ -552,11 +528,11 @@ SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab) /* Add a struct/union entry and return it */ { /* Do we have an entry with this name already? */ - SymEntry* Entry = FindSymInTable (StructTab, Name, HashStr (Name)); + SymEntry* Entry = FindSymInTable (TagTab, Name, HashStr (Name)); if (Entry) { /* We do have an entry. This may be a forward, so check it. */ - if (Entry->Flags != SC_STRUCT) { + if ((Entry->Flags & SC_STRUCT) == 0) { /* Existing symbol is not a struct */ Error (ERR_SYMBOL_KIND); } else if (Size > 0 && Entry->V.S.Size > 0) { @@ -580,7 +556,7 @@ SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab) Entry->V.S.Size = Size; /* Add it to the current table */ - AddSymEntry (StructTab, Entry); + AddSymEntry (TagTab, Entry); } /* Return the entry */ @@ -786,6 +762,14 @@ SymTable* GetSymTab (void) +int SymIsLocal (SymEntry* Sym) +/* Return true if the symbol is defined in the highest lexical level */ +{ + return (Sym->Owner == SymTab || Sym->Owner == TagTab); +} + + + static int EqualSymTables (SymTable* Tab1, SymTable* Tab2) /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */ { @@ -825,6 +809,7 @@ int EqualTypes (const type* Type1, const type* Type2) SymTable* Tab2; FuncDesc* F1; FuncDesc* F2; + int Ok; /* Shortcut here: If the pointers are identical, the types are identical */ @@ -841,17 +826,36 @@ int EqualTypes (const type* Type1, const type* Type2) /* Compare the function descriptors */ F1 = DecodePtr (Type1+1); F2 = DecodePtr (Type2+1); - if ((F1->Flags & ~FD_IMPLICIT) != (F2->Flags & ~FD_IMPLICIT)) { - /* Flags differ */ - return 0; + + /* If one of the functions is implicitly declared, both + * functions are considered equal. If one of the functions is + * old style, and the other is empty, the functions are + * considered equal. + */ + if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) { + Ok = 1; + } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) { + Ok = 1; + } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) { + Ok = 1; + } else { + Ok = 0; } - /* Compare the parameter lists */ - if (EqualSymTables (F1->SymTab, F2->SymTab) == 0 || - EqualSymTables (F1->StructTab, F2->StructTab) == 0 || - EqualSymTables (F1->EnumTab, F2->EnumTab) == 0) { - /* One of the tables is not identical */ - return 0; + if (!Ok) { + + /* Check the remaining flags */ + if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) { + /* Flags differ */ + return 0; + } + + /* Compare the parameter lists */ + if (EqualSymTables (F1->SymTab, F2->SymTab) == 0 || + EqualSymTables (F1->TagTab, F2->TagTab) == 0) { + /* One of the tables is not identical */ + return 0; + } } /* Skip the FuncDesc pointers to compare the return type */ diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index 996941ebf..5c37f2186 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -117,11 +117,11 @@ void LeaveStructLevel (void); SymEntry* FindSym (const char* Name); /* Find the symbol with the given name */ -SymEntry* FindStructSym (const char* Name); -/* Find the symbol with the given name in the struct table */ +SymEntry* FindLocalSym (const char* Name); +/* Find the symbol with the given name in the current symbol table only */ -SymEntry* FindEnumSym (const char* Name); -/* Find the symbol with the given name in the enum table */ +SymEntry* FindTagSym (const char* Name); +/* Find the symbol with the given name in the tag table */ SymEntry* FindStructField (const type* TypeArray, const char* Name); /* Find a struct field in the fields list */ @@ -160,6 +160,9 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags); SymTable* GetSymTab (void); /* Return the current symbol table */ +int SymIsLocal (SymEntry* Sym); +/* Return true if the symbol is defined in the highest lexical level */ + int EqualTypes (const type* t1, const type* t2); /* Recursively compare two types. Return 1 if the types match, return 0 * otherwise. -- 2.39.5