mirror of
https://github.com/cc65/cc65.git
synced 2025-01-26 17:36:57 +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:
parent
04dee08f58
commit
9cc25f13b6
322
src/cc65/compile.c
Normal file
322
src/cc65/compile.c
Normal 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
57
src/cc65/compile.h
Normal 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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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'",
|
||||
};
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
288
src/cc65/expr.c
288
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
266
src/cc65/main.c
266
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;
|
||||
|
@ -15,6 +15,7 @@ OBJS = anonname.o \
|
||||
asmline.o \
|
||||
check.o \
|
||||
codegen.o \
|
||||
compile.o \
|
||||
ctrans.o \
|
||||
datatype.o \
|
||||
declare.o \
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
104
src/cc65/stmt.c
104
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 ();
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user