--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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 ();
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
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;
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 ();
}
}
static void optionalint (void)
/* Eat an optional "int" token */
{
- if (curtok == INT) {
+ if (curtok == TOK_INT) {
/* Skip it */
- gettok ();
+ NextToken ();
}
}
static void optionalsigned (void)
/* Eat an optional "signed" token */
{
- if (curtok == SIGNED) {
+ if (curtok == TOK_SIGNED) {
/* Skip it */
- gettok ();
+ NextToken ();
}
}
/* 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:
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;
}
AddEnumSym (Ident, EnumVal++);
/* Check for end of definition */
- if (curtok != COMMA)
+ if (curtok != TOK_COMMA)
break;
- gettok ();
+ NextToken ();
}
ConsumeRCurly ();
}
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;
}
}
- 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 ();
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;
/* 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;
}
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;
}
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:
}
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:
}
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 */
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;
}
-static FuncDesc* ParseFuncDecl (void)
-/* Parse the argument list of a function. */
+static type* ParamTypeCvt (type* T)
+/* If T is an array, convert it to a pointer else do nothing. Return the
+ * resulting type.
+ */
{
- unsigned UnnamedCount = 0;
- unsigned Offs;
- SymEntry* Sym;
- type* Type;
+ if (IsArray (T)) {
+ T += DECODE_SIZE;
+ T[0] = T_PTR;
+ }
+ return T;
+}
- /* Create a new function descriptor */
- FuncDesc* F = NewFuncDesc ();
- /* Enter a new lexical level */
- EnterFunctionLevel ();
- /* Check for an empty or void parameter list */
- if (curtok == RPAREN) {
- /* Parameter list is empty */
- F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
- } else if (curtok == VOID && nxttok == RPAREN) {
- /* Parameter list declared as void */
- gettok ();
- F->Flags |= FD_VOID_PARAM;
+static void ParseOldStyleParamList (FuncDesc* F)
+/* Parse an old style (K&R) parameter list */
+{
+ /* Parse params */
+ while (curtok != TOK_RPAREN) {
+
+ /* List of identifiers expected */
+ if (curtok != TOK_IDENT) {
+ Error (ERR_IDENT_EXPECTED);
+ }
+
+ /* Create a symbol table entry with type int */
+ AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
+
+ /* Count arguments */
+ ++F->ParamCount;
+
+ /* Skip the identifier */
+ NextToken ();
+
+ /* Check for more parameters */
+ if (curtok == TOK_COMMA) {
+ NextToken ();
+ } else {
+ break;
+ }
+ }
+
+ /* Skip right paren. We must explicitly check for one here, since some of
+ * the breaks above bail out without checking.
+ */
+ ConsumeRParen ();
+
+ /* An optional list of type specifications follows */
+ while (curtok != TOK_LCURLY) {
+
+ DeclSpec Spec;
+
+ /* Read the declaration specifier */
+ ParseDeclSpec (&Spec, SC_AUTO, T_INT);
+
+ /* We accept only auto and register as storage class specifiers, but
+ * we ignore all this, since we use auto anyway.
+ */
+ if ((Spec.StorageClass & SC_AUTO) == 0 &&
+ (Spec.StorageClass & SC_REGISTER) == 0) {
+ Error (ERR_ILLEGAL_STORAGE_CLASS);
+ }
+
+ /* Parse a comma separated variable list */
+ while (1) {
+
+ Declaration Decl;
+
+ /* Read the parameter */
+ ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
+ if (Decl.Ident[0] != '\0') {
+
+ /* We have a name given. Search for the symbol */
+ SymEntry* Sym = FindLocalSym (Decl.Ident);
+ if (Sym) {
+ /* Found it, change the default type to the one given */
+ ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
+ } else {
+ Error (ERR_UNKNOWN_IDENT, Decl.Ident);
+ }
+ }
+
+ if (curtok == TOK_COMMA) {
+ NextToken ();
+ } else {
+ break;
+ }
+
+ }
+
+ /* Variable list must be semicolon terminated */
+ ConsumeSemi ();
}
+}
+
+
+static void ParseAnsiParamList (FuncDesc* F)
+/* Parse a new style (ANSI) parameter list */
+{
/* Parse params */
- while (curtok != RPAREN) {
+ while (curtok != TOK_RPAREN) {
+
+ DeclSpec Spec;
+ Declaration Decl;
- DeclSpec Spec;
- Declaration Decl;
/* Allow an ellipsis as last parameter */
- if (curtok == ELLIPSIS) {
- gettok ();
+ if (curtok == TOK_ELLIPSIS) {
+ NextToken ();
F->Flags |= FD_ELLIPSIS;
break;
}
/* 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;
}
*/
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 */
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 */
}
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;
} 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;
+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) */
{
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);
}
- if (curtok != COMMA) {
+ if (curtok != TOK_COMMA) {
break;
}
- gettok ();
+ NextToken ();
- } while (curtok != RCURLY);
+ } while (curtok != TOK_RCURLY);
ConsumeRCurly ();
}
/* 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 */
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 ();
}
/* 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 */
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 */
"`%s' is defined but never used",
"Constant is long",
"`/*' found inside a comment",
+ "Useless declaration",
};
"Illegal size of data type",
"__fastcall__ is not allowed for C functions",
"Variable has unknown size",
+ "Unknown identifier: `%s'",
};
WARN_UNUSED_ITEM,
WARN_CONSTANT_IS_LONG,
WARN_NESTED_COMMENT,
- WARN_COUNT /* Warning count */
+ WARN_USELESS_DECL,
+ WARN_COUNT /* Warning count */
};
/* Error numbers */
ERR_ILLEGAL_SIZE,
ERR_FASTCALL,
ERR_UNKNOWN_SIZE,
+ ERR_UNKNOWN_IDENT,
ERR_COUNT /* Error count */
};
} 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 };
/* 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;
{
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))
);
}
ParamSize = 0;
ParamCount = 0;
Ellipsis = 0;
- while (curtok != RPAREN) {
+ while (curtok != TOK_RPAREN) {
/* Add a hint for the optimizer */
AddCodeHint ("param:start");
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 */
*/
{
/* 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 */
}
/* Skip the string token */
- gettok ();
+ NextToken ();
/* Closing paren needed */
ConsumeRParen ();
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 ();
}
/* Identifier? */
- if (curtok == IDENT) {
+ if (curtok == TOK_IDENT) {
SymEntry* Sym;
ident Ident;
if (Sym) {
/* We found the symbol - skip the name token */
- gettok ();
+ NextToken ();
/* The expression type is the symbol type */
lval->e_tptr = Sym->Type;
/* 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.
}
/* 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;
}
/* __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 */
}
/* Skip the bracket */
- gettok ();
+ NextToken ();
/* Get the type of left side */
tptr1 = lval->e_tptr;
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;
/* 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);
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)) {
}
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) {
unsigned flags;
unsigned long val;
- gettok ();
+ NextToken ();
if ((k = hie10 (lval)) == 0) {
Error (ERR_LVALUE_EXPECTED);
return;
{
unsigned flags;
- gettok ();
+ NextToken ();
if (k == 0) {
Error (ERR_LVALUE_EXPECTED);
return;
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 */
/* 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;
unsigned rflags;
/* Skip the left paren */
- gettok ();
+ NextToken ();
/* Read the type */
ParseType (Type);
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;
}
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;
}
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);
}
}
return 0;
- case SIZEOF:
- gettok ();
+ case TOK_SIZEOF:
+ NextToken ();
if (istypeexpr ()) {
type Type[MAXTYPELEN];
- gettok ();
+ NextToken ();
lval->e_const = SizeOf (ParseType (Type));
ConsumeRParen ();
} else {
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;
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 */
/* Remember the operator token, then skip it */
tok = curtok;
- gettok ();
+ NextToken ();
/* Get the lhs on stack */
Mark1 = GetCodePos ();
/* 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) {
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 */
/* Remember the operator token, then skip it */
tok = curtok;
- gettok ();
+ NextToken ();
/* Get the lhs on stack */
Mark1 = GetCodePos ();
/* Skip the PLUS token */
- gettok ();
+ NextToken ();
/* Get the left hand side type, initialize operation flags */
lhst = lval->e_tptr;
/* Skip the MINUS token */
- gettok ();
+ NextToken ();
/* Get the left hand side type, initialize operation flags */
lhst = lval->e_tptr;
/* 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);
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;
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);
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 */
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) {
BoolOp = 1;
/* while there's more expr */
- while (curtok == DBAR) {
+ while (curtok == TOK_BOOL_OR) {
/* skip the || */
- gettok ();
+ NextToken ();
/* Get a subexpr */
AndOp = 0;
*/
#if 0
/* Seems this sometimes generates wrong code */
- if (curtok == DBAR && !AndOp) {
+ if (curtok == TOK_BOOL_OR && !AndOp) {
g_truejump (CF_NONE, TrueLab);
}
#else
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;
CodeMark Mark;
int MustScale;
- gettok ();
+ NextToken ();
if (k == 0) {
Error (ERR_LVALUE_EXPECTED);
return;
}
/* Skip the operator */
- gettok ();
+ NextToken ();
/* Check if we have a pointer expression and must scale rhs */
MustScale = (lval->e_tptr [0] == T_PTR);
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);
} 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);
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 {
}
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;
int k;
k = hie1 (lval);
- while (curtok == COMMA) {
- gettok ();
+ while (curtok == TOK_COMMA) {
+ NextToken ();
k = hie1 (lval);
}
return k;
* 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);
}
}
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;
/* 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 */
};
/* 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;
}
}
/* Need a starting curly brace */
- if (curtok != LCURLY) {
+ if (curtok != TOK_LCURLY) {
Error (ERR_LCURLY_EXPECTED);
}
/* Process a goto statement. */
{
/* Eat the "goto" */
- gettok ();
+ NextToken ();
/* Label name must follow */
- if (curtok != IDENT) {
+ if (curtok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
}
/* Eat the label name */
- gettok ();
+ NextToken ();
}
g_defloclabel (Entry->V.Label);
/* Eat the ident and colon */
- gettok ();
- gettok ();
+ NextToken ();
+ NextToken ();
}
#include "codegen.h"
#include "declare.h"
#include "expr.h"
-#include "function.h" /* ## */
+#include "function.h"
#include "global.h"
#include "mem.h"
#include "symtab.h"
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 */
}
/* 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;
}
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);
/* Change SC in case it was register */
SymbolSC = (SymbolSC & ~SC_REGISTER) | SC_AUTO;
- if (curtok == ASGN) {
+ if (curtok == TOK_ASSIGN) {
struct expent lval;
AutoSpace = 0;
/* Skip the '=' */
- gettok ();
+ NextToken ();
/* Setup the type flags for the assignment */
flags = Size == 1? CF_FORCECHAR : CF_NONE;
g_res (Size);
/* Allow assignments */
- if (curtok == ASGN) {
+ if (curtok == TOK_ASSIGN) {
struct expent lval;
g_usecode ();
/* Skip the '=' */
- gettok ();
+ NextToken ();
/* Get the expression into the primary */
expression1 (&lval);
} else if ((SymbolSC & SC_STATIC) == SC_STATIC) {
/* Static data */
- if (curtok == ASGN) {
+ if (curtok == TOK_ASSIGN) {
/* Initialization ahead, switch to data segment */
g_usedata ();
g_defloclabel (ldata = GetLabel ());
/* Skip the '=' */
- gettok ();
+ NextToken ();
/* Allow initialization of static vars */
ParseInit (Decl.Type);
/* 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 ();
}
}
}
}
-
+
#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"
/*****************************************************************************/
-/* code */
+/* 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 ();
- 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;
asmline.o \
check.o \
codegen.o \
+ compile.o \
ctrans.o \
datatype.o \
declare.o \
asmline.obj \
check.obj \
codegen.obj \
+ compile.obj \
ctrans.obj \
datatype.obj \
declare.obj \
FILE asmline.obj
FILE check.obj
FILE codegen.obj
+FILE compile.obj
FILE ctrans.obj
FILE datatype.obj
FILE declare.obj
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 */
}
/* Skip the string (or error) token */
- gettok ();
+ NextToken ();
}
int Pragma;
/* Skip the token itself */
- gettok ();
+ NextToken ();
/* Identifier must follow */
- if (curtok != IDENT) {
+ if (curtok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
return;
}
}
/* Skip the identifier and check for an open paren */
- gettok ();
+ NextToken ();
ConsumeLParen ();
/* Switch for the different pragmas */
static int Pass1 (char* from, char* to)
/* Preprocessor pass 1. Remove whitespace and comments. */
{
- int c;
+ int c;
int done;
ident Ident;
int HaveParen;
xlateline ();
/* Prime the token pump (remove old tokens from the stream) */
- gettok ();
- gettok ();
+ NextToken ();
+ NextToken ();
/* Call the expression parser */
constexpr (&lval);
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]))
if (K && (K->Type != TT_EXT || ANSI == 0)) {
return K->Tok;
} else {
- return IDENT;
+ return TOK_IDENT;
}
}
}
/* 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 */
}
/* Parse a quoted string */
{
nxtval = GetLiteralOffs ();
- nxttok = SCONST;
+ nxttok = TOK_SCONST;
/* Be sure to concatenate strings */
while (*lptr == '\"') {
-void gettok (void)
+void NextToken (void)
/* Get next token from input stream */
{
char c;
/* Skip spaces and read the next line if needed */
if (skipwhite () == 0) {
/* End of file reached */
- nxttok = CEOF;
+ nxttok = TOK_CEOF;
return;
}
/* 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;
}
/* 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;
/* __func__ is only defined in functions */
if (CurrentFunc) {
nxtval = AddLiteral (GetFuncName (CurrentFunc));
- nxttok = SCONST;
+ nxttok = TOK_SCONST;
return;
}
}
/* No reserved word but identifier */
strcpy (NextTok.Ident, token);
- NextTok.Tok = IDENT;
+ NextTok.Tok = TOK_IDENT;
return;
}
case '!':
if (*++lptr == '=') {
- SetTok (NE);
+ SetTok (TOK_NE);
} else {
- nxttok = BANG;
+ nxttok = TOK_BOOL_NOT;
}
break;
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;
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 '#':
/* OOPS - should not happen */
Error (ERR_CPP_DIRECTIVE_EXPECTED);
}
- nxttok = PRAGMA;
+ nxttok = TOK_PRAGMA;
break;
default:
-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);
}
void ConsumeColon (void)
/* Check for a colon and skip it. */
{
- Consume (COLON, ERR_COLON_EXPECTED);
+ Consume (TOK_COLON, ERR_COLON_EXPECTED);
}
/* 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 ();
}
}
}
void ConsumeLParen (void)
/* Check for a left parenthesis and skip it */
{
- Consume (LPAREN, ERR_LPAREN_EXPECTED);
+ Consume (TOK_LPAREN, ERR_LPAREN_EXPECTED);
}
void ConsumeRParen (void)
/* Check for a right parenthesis and skip it */
{
- Consume (RPAREN, ERR_RPAREN_EXPECTED);
+ Consume (TOK_RPAREN, ERR_RPAREN_EXPECTED);
}
void ConsumeLBrack (void)
/* Check for a left bracket and skip it */
{
- Consume (LBRACK, ERR_LBRACK_EXPECTED);
+ Consume (TOK_LBRACK, ERR_LBRACK_EXPECTED);
}
void ConsumeRBrack (void)
/* Check for a right bracket and skip it */
{
- Consume (RBRACK, ERR_RBRACK_EXPECTED);
+ Consume (TOK_RBRACK, ERR_RBRACK_EXPECTED);
}
void ConsumeLCurly (void)
/* Check for a left curly brace and skip it */
{
- Consume (LCURLY, ERR_LCURLY_EXPECTED);
+ Consume (TOK_LCURLY, ERR_LCURLY_EXPECTED);
}
void ConsumeRCurly (void)
/* Check for a right curly brace and skip it */
{
- Consume (RCURLY, ERR_RCURLY_EXPECTED);
+ Consume (TOK_RCURLY, ERR_RCURLY_EXPECTED);
}
/*****************************************************************************/
-/* token definitions */
+/* Token definitions */
/*****************************************************************************/
-#define CEOF 0
-
-#define AUTO 10
-#define EXTERN 11
-#define REGISTER 12
-#define STATIC 13
-#define TYPEDEF 14
-#define ENUM 15
-#define CONST 16
-#define VOLATILE 17
-
-#define FIRSTTYPE 19
-#define CHAR 19
-#define INT 20
-#define DOUBLE 21
-#define FLOAT 22
-#define LONG 23
-#define UNSIGNED 24
-#define SIGNED 25
-#define SHORT 26
-#define STRUCT 27
-#define UNION 28
-#define VOID 29
-#define LASTTYPE 29
-
-#define DO 30
-#define FOR 31
-#define GOTO 32
-#define IF 33
-#define RETURN 34
-#define SWITCH 35
-#define WHILE 36
-
-#define ASM 40
-#define CASE 41
-#define DEFAULT 42
-#define BREAK 43
-#define CONTINUE 44
-#define ELSE 45
-#define ELLIPSIS 46
-#define SIZEOF 47
-
-#define IDENT 50
-#define SEMI 51
-
-/* primary operators */
-#define LBRACK 52
-#define LPAREN 53
-#define DOT 54
-#define PREF 55
-
-#define LCURLY 56
-#define RBRACK 57
-#define COMP 58
-#define INC 59
-#define PASGN 60
-#define PLUS 61
-#define COMMA 62
-#define DEC 63
-#define SASGN 64
-#define RCURLY 65
-#define MINUS 66
-#define MASGN 67
-#define STAR 68
-#define DASGN 69
-#define DIV 70
-#define DAMP 71
-#define AASGN 72
-#define AMP 73
-#define NE 74
-#define BANG 75
-#define DBAR 76
-#define OASGN 77
-#define BAR 78
-#define EQ 79
-#define ASGN 80
-#define SLASGN 81
-#define ASL 82
-
-/* inequalities */
-#define LE 83
-#define LT 84
-#define GE 85
-#define GT 86
-
-#define SRASGN 87
-#define ASR 88
-#define XOASGN 89
-#define XOR 90
-#define MOASGN 91
-#define MOD 92
-#define QUEST 93
-#define COLON 94
-#define RPAREN 95
-#define SCONST 96
-#define ICONST 97
-#define CCONST 98
-#define FCONST 99
-
-#define FASTCALL 100
-#define AX 101
-#define EAX 102
-
-#define PRAGMA 110
+typedef enum token_t {
+ TOK_CEOF,
+
+ TOK_AUTO,
+ TOK_EXTERN,
+ TOK_REGISTER,
+ TOK_STATIC,
+ TOK_TYPEDEF,
+ TOK_ENUM,
+ TOK_CONST,
+ TOK_VOLATILE,
+
+ /* Tokens denoting types */
+ TOK_FIRSTTYPE,
+ TOK_CHAR = TOK_FIRSTTYPE,
+ TOK_INT,
+ TOK_DOUBLE,
+ TOK_FLOAT,
+ TOK_LONG,
+ TOK_UNSIGNED,
+ TOK_SIGNED,
+ TOK_SHORT,
+ TOK_STRUCT,
+ TOK_UNION,
+ TOK_VOID,
+ TOK_LASTTYPE = TOK_VOID,
+
+ /* Control statements */
+ TOK_DO,
+ TOK_FOR,
+ TOK_GOTO,
+ TOK_IF,
+ TOK_RETURN,
+ TOK_SWITCH,
+ TOK_WHILE,
+
+ TOK_ASM,
+ TOK_CASE,
+ TOK_DEFAULT,
+ TOK_BREAK,
+ TOK_CONTINUE,
+ TOK_ELSE,
+ TOK_ELLIPSIS,
+ TOK_SIZEOF,
+
+ TOK_IDENT,
+ TOK_SEMI,
+
+ /* Primary operators */
+ TOK_LBRACK,
+ TOK_LPAREN,
+ TOK_DOT,
+ TOK_PTR_REF,
+
+ TOK_LCURLY,
+ TOK_RBRACK,
+ TOK_COMP,
+ TOK_INC,
+ TOK_PLUS_ASSIGN,
+ TOK_PLUS,
+ TOK_COMMA,
+ TOK_DEC,
+ TOK_MINUS_ASSIGN,
+ TOK_RCURLY,
+ TOK_MINUS,
+ TOK_MUL_ASSIGN,
+ TOK_STAR,
+ TOK_DIV_ASSIGN,
+ TOK_DIV,
+ TOK_BOOL_AND,
+ TOK_AND_ASSIGN,
+ TOK_AND,
+ TOK_NE,
+ TOK_BOOL_NOT,
+ TOK_BOOL_OR,
+ TOK_OR_ASSIGN,
+ TOK_OR,
+ TOK_EQ,
+ TOK_ASSIGN,
+ TOK_SHL_ASSIGN,
+ TOK_SHL,
+
+ /* Inequalities */
+ TOK_LE,
+ TOK_LT,
+ TOK_GE,
+ TOK_GT,
+
+ TOK_SHR_ASSIGN,
+ TOK_SHR,
+ TOK_XOR_ASSIGN,
+ TOK_XOR,
+ TOK_MOD_ASSIGN,
+ TOK_MOD,
+ TOK_QUEST,
+ TOK_COLON,
+ TOK_RPAREN,
+ TOK_SCONST,
+ TOK_ICONST,
+ TOK_CCONST,
+ TOK_FCONST,
+
+ TOK_ATTRIBUTE,
+ TOK_FASTCALL,
+ TOK_AX,
+ TOK_EAX,
+
+ TOK_PRAGMA
+} token_t;
/* 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 */
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.
*/
int gotbreak;
/* Skip the if */
- gettok ();
+ NextToken ();
/* Generate a jump label and parse the condition */
flab1 = GetLabel ();
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
} 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
int loop;
int lab;
- gettok ();
+ NextToken ();
loop = GetLabel ();
lab = GetLabel ();
addloop (oursp, loop, lab, 0, 0);
* 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 {
/* Do loop */
statement ();
- Consume (WHILE, ERR_WHILE_EXPECTED);
+ Consume (TOK_WHILE, ERR_WHILE_EXPECTED);
test (loop, 1);
ConsumeSemi ();
g_defloclabel (lab);
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);
}
{
struct loopdesc* l;
- gettok ();
+ NextToken ();
if ((l = currentloop ()) == 0) {
/* Error: No current loop */
return;
{
struct loopdesc* l;
- gettok ();
+ NextToken ();
if ((l = currentloop ()) == 0) {
/* Error: Not in loop */
return;
/* 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.
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);
/* 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 ();
} 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 ();
}
}
/* Parse statements */
- if (curtok != RCURLY) {
+ if (curtok != TOK_RCURLY) {
havebreak = statement ();
}
}
}
/* Eat the closing curly brace */
- gettok ();
+ NextToken ();
/* Define the exit label and, if there's a next label left, create this
* one, too.
/* 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);
++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 ();
}
}
}
/* Eat the closing curly brace */
- gettok ();
+ NextToken ();
/* If the last statement doesn't have a break or return, add one */
if (!havebreak) {
struct expent eval; /* Switch statement expression */
/* Eat the "switch" */
- gettok ();
+ NextToken ();
/* Read the switch expression */
ConsumeLParen ();
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);
}
ConsumeSemi ();
g_defloclabel (linc);
- if (curtok != RPAREN) { /* exp3 */
+ if (curtok != TOK_RPAREN) { /* exp3 */
expression (&lval3);
}
ConsumeRParen ();
struct expent lval;
/* */
- if (curtok == IDENT && nxttok == COLON) {
+ if (curtok == TOK_IDENT && nxttok == TOK_COLON) {
/* Special handling for a label */
DoLabel ();
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;
int oldsp;
/* eat LCURLY */
- gettok ();
+ NextToken ();
/* Remember the stack at block entry */
oldsp = oursp;
/* 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 ();
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-
+
#include "../common/hashstr.h"
#include "asmcode.h"
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;
/* 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);
}
/* 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;
}
S->PrevTab = SymTab;
SymTab = S;
- /* Get a new struct table and make it current */
- S = NewSymTable (SYMTAB_SIZE_FUNCTION);
- S->PrevTab = StructTab;
- StructTab = S;
-
- /* Get a new enum table and make it current */
+ /* Get a new tag table and make it current */
S = NewSymTable (SYMTAB_SIZE_FUNCTION);
- S->PrevTab = EnumTab;
- EnumTab = S;
+ S->PrevTab = TagTab;
+ TagTab = S;
/* Create and assign a new label table */
LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
--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;
}
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);
}
/* Don't delete the tables */
- SymTab = SymTab->PrevTab;
- StructTab = StructTab->PrevTab;
- EnumTab = EnumTab->PrevTab;
+ SymTab = SymTab->PrevTab;
+ TagTab = TagTab->PrevTab;
LabelTab = 0;
}
S->PrevTab = SymTab;
SymTab = S;
- /* Get a new struct table and make it current */
- S = NewSymTable (SYMTAB_SIZE_BLOCK);
- S->PrevTab = StructTab;
- StructTab = S;
-
- /* Get a new enum table and make it current */
+ /* Get a new tag table and make it current */
S = NewSymTable (SYMTAB_SIZE_BLOCK);
- S->PrevTab = EnumTab;
- EnumTab = S;
+ S->PrevTab = TagTab;
+ TagTab = S;
}
CheckSymTable (SymTab);
/* Don't delete the tables */
- SymTab = SymTab->PrevTab;
- StructTab = StructTab->PrevTab;
- EnumTab = EnumTab->PrevTab;
+ SymTab = SymTab->PrevTab;
+ TagTab = TagTab->PrevTab;
}
-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);
}
/* 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) {
Entry->V.S.Size = Size;
/* Add it to the current table */
- AddSymEntry (StructTab, Entry);
+ AddSymEntry (TagTab, Entry);
}
/* Return the entry */
+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 */
{
SymTable* Tab2;
FuncDesc* F1;
FuncDesc* F2;
+ int Ok;
/* Shortcut here: If the pointers are identical, the types are identical */
/* 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 */
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 */
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.