#include <string.h>
/* common */
+#include "cddefs.h"
#include "check.h"
#include "hashstr.h"
#include "symdefs.h"
#include "error.h"
#include "expr.h"
#include "objfile.h"
+#include "scanner.h"
#include "symtab.h"
#define SF_GLOBAL 0x0010 /* Global symbol */
#define SF_ZP 0x0020 /* Declared as zeropage symbol */
#define SF_ABS 0x0040 /* Declared as absolute symbol */
+#define SF_LABEL 0x0080 /* Used as a label */
#define SF_INDEXED 0x0800 /* Index is valid */
#define SF_CONST 0x1000 /* The symbol has a constant value */
#define SF_MULTDEF 0x2000 /* Multiply defined symbol */
#define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
#define SF_DBGINFOVAL (SF_DEFINED)
-
-
/* Structure of a symbol table entry */
-struct SymEntry_ {
+struct SymEntry {
SymEntry* Left; /* Lexically smaller entry */
- SymEntry* Right; /* Lexically larger entry */
- SymEntry* List; /* List of all entries */
+ SymEntry* Right; /* Lexically larger entry */
+ SymEntry* List; /* List of all entries */
SymEntry* Locals; /* Root of subtree for local symbols */
- struct SymTable_* SymTab; /* Table this symbol is in, 0 for locals */
+ struct SymTable* SymTab; /* Table this symbol is in, 0 for locals */
FilePos Pos; /* File position for this symbol */
unsigned Flags; /* Symbol flags */
unsigned Index; /* Index of import/export entries */
union {
- struct ExprNode_* Expr; /* Expression if CONST not set */
+ struct ExprNode* Expr; /* Expression if CONST not set */
long Val; /* Value (if CONST set) */
- SymEntry* Sym; /* Symbol (if trampoline entry) */
+ SymEntry* Sym; /* Symbol (if trampoline entry) */
} V;
+ unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */
+ /* ...actually value+1 (used as flag) */
char Name [1]; /* Dynamic allocation */
};
/* Definitions for the hash table */
-#define MAIN_HASHTAB_SIZE 213
-#define SUB_HASHTAB_SIZE 53
-typedef struct SymTable_ SymTable;
-struct SymTable_ {
- unsigned TableSlots; /* Number of hash table slots */
- unsigned TableEntries; /* Number of entries in the table */
+#define MAIN_HASHTAB_SIZE 213
+#define SUB_HASHTAB_SIZE 53
+typedef struct SymTable SymTable;
+struct SymTable {
+ unsigned TableSlots; /* Number of hash table slots */
+ unsigned TableEntries; /* Number of entries in the table */
SymTable* BackLink; /* Link to enclosing scope if any */
- SymEntry* Table [1]; /* Dynamic allocation */
+ SymEntry* Table [1]; /* Dynamic allocation */
};
+/* Arguments for SymFind */
+#define SF_FIND_EXISTING 0
+#define SF_ALLOC_NEW 1
+
+
+
/* Symbol table variables */
static SymEntry* SymList = 0; /* List of all symbol table entries */
static SymEntry* SymLast = 0; /* Pointer to last defined symbol */
S = xmalloc (sizeof (SymEntry) + Len);
/* Initialize the entry */
- S->Left = 0;
- S->Right = 0;
- S->Locals = 0;
- S->SymTab = 0;
- S->Flags = 0;
- S->V.Expr = 0;
- S->Pos = CurPos;
+ S->Left = 0;
+ S->Right = 0;
+ S->Locals = 0;
+ S->SymTab = 0;
+ S->Pos = CurPos;
+ S->Flags = 0;
+ S->V.Expr = 0;
+ memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
memcpy (S->Name, Name, Len+1);
/* Insert it into the list of all entries */
static SymEntry* SymRefInternal (SymTable* Table, const char* Name)
/* Search for the symbol in the given table and return it */
{
- SymEntry* S;
-
/* Try to find the symbol, create a new one if the symbol does not exist */
- S = SymFind (Table, Name, 1);
+ SymEntry* S = SymFind (Table, Name, SF_ALLOC_NEW);
/* Mark the symbol as referenced */
S->Flags |= SF_REFERENCED;
-void SymDef (const char* Name, ExprNode* Expr, int ZP)
+void SymDef (const char* Name, ExprNode* Expr, int ZP, int Label)
/* Define a new symbol */
{
- SymEntry* S;
-
/* Do we have such a symbol? */
- S = SymFind (SymTab, Name, 1);
+ SymEntry* S = SymFind (SymTab, Name, SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
- Error (ERR_SYM_ALREADY_IMPORT);
+ Error (ERR_SYM_ALREADY_IMPORT, Name);
return;
}
if (S->Flags & SF_DEFINED) {
if (ZP) {
S->Flags |= SF_ZP;
}
+ if (Label) {
+ S->Flags |= SF_LABEL;
+ }
/* If the symbol is a ZP symbol, check if the value is in correct range */
if (S->Flags & SF_ZP) {
}
/* Do we have such a symbol? */
- S = SymFind (SymTab, Name, 1);
+ S = SymFind (SymTab, Name, SF_ALLOC_NEW);
if (S->Flags & SF_DEFINED) {
Error (ERR_SYM_ALREADY_DEFINED, Name);
S->Flags |= SF_MULTDEF;
}
if (S->Flags & SF_EXPORT) {
/* The symbol is already marked as exported symbol */
- Error (ERR_SYM_ALREADY_EXPORT);
+ Error (ERR_SYM_ALREADY_EXPORT, Name);
return;
}
}
/* Do we have such a symbol? */
- S = SymFind (SymTab, Name, 1);
+ S = SymFind (SymTab, Name, SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
- Error (ERR_SYM_ALREADY_IMPORT);
+ Error (ERR_SYM_ALREADY_IMPORT, Name);
return;
}
}
/* Search for this symbol, create a new entry if needed */
- S = SymFind (SymTab, Name, 1);
+ S = SymFind (SymTab, Name, SF_ALLOC_NEW);
/* If the symbol is already marked as import or export, check the
* size of the definition, then bail out. */
+void SymConDes (const char* Name, unsigned Type, unsigned Prio)
+/* Mark the given symbol as a module constructor/destructor. This will also
+ * mark the symbol as an export. Initializers may never be zero page symbols.
+ */
+{
+ SymEntry* S;
+
+ /* Check the parameters */
+#if (CD_TYPE_MIN != 0)
+ CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
+#else
+ CHECK (Type <= CD_TYPE_MAX);
+#endif
+ CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
+
+ /* Don't accept local symbols */
+ if (IsLocal (Name)) {
+ Error (ERR_ILLEGAL_LOCAL_USE);
+ return;
+ }
+
+ /* Do we have such a symbol? */
+ S = SymFind (SymTab, Name, SF_ALLOC_NEW);
+ if (S->Flags & SF_IMPORT) {
+ /* The symbol is already marked as imported external symbol */
+ Error (ERR_SYM_ALREADY_IMPORT, Name);
+ return;
+ }
+
+ /* If the symbol is marked as global, silently remove the global flag */
+ if (S->Flags & SF_GLOBAL) {
+ S->Flags &= ~SF_GLOBAL;
+ }
+
+ /* Check if the symbol was not already defined as ZP symbol */
+ if ((S->Flags & SF_ZP) != 0) {
+ Error (ERR_SYM_REDECL_MISMATCH);
+ }
+
+ /* If the symbol was already declared as a condes, check if the new
+ * priority value is the same as the old one.
+ */
+ if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
+ if (S->ConDesPrio[Type] != Prio) {
+ Error (ERR_SYM_REDECL_MISMATCH);
+ }
+ }
+ S->ConDesPrio[Type] = Prio;
+
+ /* Set the symbol data */
+ S->Flags |= SF_EXPORT | SF_REFERENCED;
+}
+
+
+
int SymIsDef (const char* Name)
/* Return true if the given symbol is already defined */
{
SymEntry* S = SymFindAny (SymTab, Name);
- return S != 0 && (S->Flags & (SF_DEFINED | SF_IMPORT)) != 0;
+ return S != 0 && (S->Flags & SF_DEFINED) != 0;
}
if (S->Flags & SF_EXPORT) {
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
- PError (&S->Pos, ERR_SYM_ALREADY_IMPORT);
+ PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, S->Name);
}
Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP);
}
while (S) {
/* Ignore trampoline symbols */
if ((S->Flags & SF_TRAMPOLINE) != 0) {
- printf ("%-24s %s %s %s %s %s\n",
- S->Name,
- (S->Flags & SF_DEFINED)? "DEF" : "---",
- (S->Flags & SF_REFERENCED)? "REF" : "---",
- (S->Flags & SF_IMPORT)? "IMP" : "---",
- (S->Flags & SF_EXPORT)? "EXP" : "---",
- (S->Flags & SF_ZP)? "ZP" : "--");
+ fprintf (F,
+ "%-24s %s %s %s %s %s\n",
+ S->Name,
+ (S->Flags & SF_DEFINED)? "DEF" : "---",
+ (S->Flags & SF_REFERENCED)? "REF" : "---",
+ (S->Flags & SF_IMPORT)? "IMP" : "---",
+ (S->Flags & SF_EXPORT)? "EXP" : "---",
+ (S->Flags & SF_ZP)? "ZP" : "--");
}
/* Next symbol */
S = S->List;
/* Write the imports list to the object file */
{
SymEntry* S;
-
+
/* Tell the object file module that we're about to start the imports */
ObjStartImports ();
+static unsigned char GetExprMask (SymEntry* S)
+/* Return the expression bits for the given symbol table entry */
+{
+ unsigned char ExprMask;
+
+ /* Check if the symbol is const */
+ ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
+
+ /* Add zeropage/abs bits */
+ ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS;
+
+ /* Add the label/equate bits */
+ ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
+
+ /* Return the mask */
+ return ExprMask;
+}
+
+
+
void WriteExports (void)
/* Write the exports list to the object file */
{
SymEntry* S;
+ unsigned Type;
/* Tell the object file module that we're about to start the exports */
ObjStartExports ();
/* Finalize an associated expression if we have one */
SymFinalize (S);
- /* Check if the symbol is const */
- ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
+ /* Get the expression bits */
+ ExprMask = GetExprMask (S);
+
+ /* Count the number of ConDes types */
+ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
+ if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
+ INC_EXP_CONDES_COUNT (ExprMask);
+ }
+ }
/* Write the type */
- if (S->Flags & SF_ZP) {
- ObjWrite8 (EXP_ZP | ExprMask);
- } else {
- ObjWrite8 (EXP_ABS | ExprMask);
+ ObjWrite8 (ExprMask);
+
+ /* Write any ConDes declarations */
+ if (GET_EXP_CONDES_COUNT (ExprMask) > 0) {
+ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
+ unsigned char Prio = S->ConDesPrio[Type];
+ if (Prio != CD_PRIO_NONE) {
+ ObjWrite8 (CD_BUILD (Type, Prio));
+ }
+ }
}
+
+ /* Write the name */
ObjWriteStr (S->Name);
- if (ExprMask == EXP_CONST) {
+
+ /* Write the value */
+ if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
/* Constant value */
ObjWrite32 (S->V.Val);
} else {
/* Expression involved */
WriteExpr (S->V.Expr);
}
+
+ /* Write the source file position */
ObjWritePos (&S->Pos);
}
S = S->List;
/* Finalize an associated expression if we have one */
SymFinalize (S);
- /* Check if the symbol is const */
- ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
+ /* Get the expression bits */
+ ExprMask = GetExprMask (S);
/* Write the type */
- if (S->Flags & SF_ZP) {
- ObjWrite8 (EXP_ZP | ExprMask);
- } else {
- ObjWrite8 (EXP_ABS | ExprMask);
- }
+ ObjWrite8 (ExprMask);
+
+ /* Write the name */
ObjWriteStr (S->Name);
- if (ExprMask == EXP_CONST) {
+
+ /* Write the value */
+ if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
/* Constant value */
ObjWrite32 (S->V.Val);
} else {
/* Expression involved */
WriteExpr (S->V.Expr);
}
+
+ /* Write the source file position */
ObjWritePos (&S->Pos);
}
S = S->List;