1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-08 15:29:37 +00:00

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
This commit is contained in:
cuz 2000-06-12 18:31:40 +00:00
parent 04dee08f58
commit 9cc25f13b6
23 changed files with 1269 additions and 976 deletions

322
src/cc65/compile.c Normal file
View File

@ -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 <stdlib.h>
#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 ();
}

57
src/cc65/compile.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;
}
}
/* Parse params */
while (curtok != RPAREN) {
/* 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 != 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 ();
}

View File

@ -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 */

View File

@ -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'",
};

View File

@ -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 */
};

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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 */
};

View File

@ -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);
}

View File

@ -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 ();
}

View File

@ -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)
}
}

View File

@ -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;

View File

@ -15,6 +15,7 @@ OBJS = anonname.o \
asmline.o \
check.o \
codegen.o \
compile.o \
ctrans.o \
datatype.o \
declare.o \

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}

View File

@ -17,115 +17,120 @@
/*****************************************************************************/
/* token definitions */
/* Token definitions */
/*****************************************************************************/
#define CEOF 0
typedef enum token_t {
TOK_CEOF,
#define AUTO 10
#define EXTERN 11
#define REGISTER 12
#define STATIC 13
#define TYPEDEF 14
#define ENUM 15
#define CONST 16
#define VOLATILE 17
TOK_AUTO,
TOK_EXTERN,
TOK_REGISTER,
TOK_STATIC,
TOK_TYPEDEF,
TOK_ENUM,
TOK_CONST,
TOK_VOLATILE,
#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
/* 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,
#define DO 30
#define FOR 31
#define GOTO 32
#define IF 33
#define RETURN 34
#define SWITCH 35
#define WHILE 36
/* Control statements */
TOK_DO,
TOK_FOR,
TOK_GOTO,
TOK_IF,
TOK_RETURN,
TOK_SWITCH,
TOK_WHILE,
#define ASM 40
#define CASE 41
#define DEFAULT 42
#define BREAK 43
#define CONTINUE 44
#define ELSE 45
#define ELLIPSIS 46
#define SIZEOF 47
TOK_ASM,
TOK_CASE,
TOK_DEFAULT,
TOK_BREAK,
TOK_CONTINUE,
TOK_ELSE,
TOK_ELLIPSIS,
TOK_SIZEOF,
#define IDENT 50
#define SEMI 51
TOK_IDENT,
TOK_SEMI,
/* primary operators */
#define LBRACK 52
#define LPAREN 53
#define DOT 54
#define PREF 55
/* Primary operators */
TOK_LBRACK,
TOK_LPAREN,
TOK_DOT,
TOK_PTR_REF,
#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
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 */
#define LE 83
#define LT 84
#define GE 85
#define GT 86
/* Inequalities */
TOK_LE,
TOK_LT,
TOK_GE,
TOK_GT,
#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
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,
#define FASTCALL 100
#define AX 101
#define EAX 102
TOK_ATTRIBUTE,
TOK_FASTCALL,
TOK_AX,
TOK_EAX,
#define PRAGMA 110
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.
*/

View File

@ -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 ();

View File

@ -37,7 +37,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#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 */
/* Get a new tag table and make it current */
S = NewSymTable (SYMTAB_SIZE_FUNCTION);
S->PrevTab = StructTab;
StructTab = S;
/* Get a new enum 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 */
/* Get a new tag table and make it current */
S = NewSymTable (SYMTAB_SIZE_BLOCK);
S->PrevTab = StructTab;
StructTab = S;
/* Get a new enum 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 */

View File

@ -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.