#include <string.h>
/* common */
+#include "cddefs.h"
#include "check.h"
#include "hashstr.h"
#include "symdefs.h"
#define SF_EXPORT 0x0004 /* Export this symbol */
#define SF_IMPORT 0x0008 /* Import this symbol */
#define SF_GLOBAL 0x0010 /* Global symbol */
-#define SF_INITIALIZER 0x0020 /* Exported initializer */
-#define SF_ZP 0x0040 /* Declared as zeropage symbol */
-#define SF_ABS 0x0080 /* Declared as absolute 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_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 */
};
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 */
-void SymDef (const char* Name, ExprNode* Expr, int ZP)
+void SymDef (const char* Name, ExprNode* Expr, int ZP, int Label)
/* Define a new symbol */
{
/* Do we have such a symbol? */
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) {
}
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;
}
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;
}
-void SymInitializer (const char* Name, int ZP)
-/* Mark the given symbol as an initializer. This will also mark the symbol as
- * an export. Initializers may never be zero page symbols, the ZP parameter
- * is supplied to make the prototype the same as the other functions (this
- * is used in pseudo.c). Passing something else but zero as ZP argument will
- * trigger an internal error.
+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 ZP parameter */
- CHECK (ZP == 0);
+ /* 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)) {
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;
}
- /* If the symbol is marked as global, check the symbol size, then do
- * silently remove the global flag
- */
+ /* If the symbol is marked as global, silently remove the global flag */
if (S->Flags & SF_GLOBAL) {
- if ((S->Flags & SF_ZP) != 0) {
- Error (ERR_SYM_REDECL_MISMATCH);
- }
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_INITIALIZER | SF_REFERENCED;
+ S->Flags |= SF_EXPORT | SF_REFERENCED;
}
/* 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;
+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);
- /* Add zeropage/abs bits */
- ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS;
-
- /* Add the initializer bits */
- if (S->Flags & SF_INITIALIZER) {
- ExprMask |= EXP_INITIALIZER;
+ /* 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 */
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);
/* Finalize an associated expression if we have one */
SymFinalize (S);
- /* 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 initializer bits */
- if (S->Flags & SF_INITIALIZER) {
- ExprMask |= EXP_INITIALIZER;
- }
+ /* Get the expression bits */
+ ExprMask = GetExprMask (S);
/* Write the type */
ObjWrite8 (ExprMask);