From 72e32b332b25bb641c122d4eb9b94239d3577ef1 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 30 Oct 2000 20:48:11 +0000 Subject: [PATCH] Working on initializers git-svn-id: svn://svn.cc65.org/cc65/trunk@411 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/error.c | 4 +-- src/ca65/pseudo.c | 36 ++++++++++++++++--- src/ca65/symtab.c | 61 +++++++++++++++++-------------- src/ca65/symtab.h | 7 ++-- src/common/symdefs.h | 33 +++++++++-------- src/ld65/dbgsyms.c | 2 +- src/ld65/exports.c | 86 ++++++++++++++++++++++++-------------------- src/od65/dump.c | 2 +- 8 files changed, 139 insertions(+), 92 deletions(-) diff --git a/src/ca65/error.c b/src/ca65/error.c index 1c4663005..358be913f 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -163,8 +163,8 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap) "Syntax error", "Symbol `%s' is already defined", "Undefined symbol `%s'", - "Symbol `%s' is marked as import", - "Symbol `%s' is marked as export", + "Symbol `%s' is already marked as import", + "Symbol `%s' is already marked as export", "Exported symbol `%s' is undefined", "Exported values must be constant", ".IF nesting too deep", diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index d93976101..9373ec01b 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -42,6 +42,7 @@ /* common */ #include "bitops.h" #include "check.h" +#include "symdefs.h" #include "tgttrans.h" /* ca65 */ @@ -727,9 +728,9 @@ static void DoInclude (void) if (Tok != TOK_STRCON) { ErrorSkip (ERR_STRCON_EXPECTED); } else { - strcpy (Name, SVal); - NextTok (); - NewInputFile (Name); + strcpy (Name, SVal); + NextTok (); + NewInputFile (Name); } } @@ -738,7 +739,34 @@ static void DoInclude (void) static void DoInitializer (void) /* Export a symbol as initializer */ { - ExportImport (SymInitializer, 0); + char Name [sizeof (SVal)]; + long Val; + + /* Symbol name follows */ + if (Tok != TOK_IDENT) { + ErrorSkip (ERR_IDENT_EXPECTED); + return; + } + strcpy (Name, SVal); + NextTok (); + + /* Optional initializer value */ + if (Tok == TOK_COMMA) { + /* Initializer value follows */ + NextTok (); + Val = ConstExpression (); + if (Val < EXP_INIT_MIN || Val > EXP_INIT_MAX) { + /* Value out of range */ + Error (ERR_RANGE); + return; + } + } else { + /* Use the default initializer value */ + Val = EXP_INIT_DEF; + } + + /* Define the symbol */ + SymInitializer (Name, (unsigned) Val); } diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index f64260330..8261572ac 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -97,6 +97,7 @@ struct SymEntry_ { long Val; /* Value (if CONST set) */ SymEntry* Sym; /* Symbol (if trampoline entry) */ } V; + unsigned char InitVal; /* Initializer value */ char Name [1]; /* Dynamic allocation */ }; @@ -158,13 +159,14 @@ static SymEntry* NewSymEntry (const char* Name) 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; + S->InitVal = 0; memcpy (S->Name, Name, Len+1); /* Insert it into the list of all entries */ @@ -482,7 +484,7 @@ void SymImport (const char* Name, int 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; } @@ -520,7 +522,7 @@ void SymExport (const char* Name, int ZP) 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; } @@ -577,18 +579,15 @@ void SymGlobal (const char* Name, int ZP) -void SymInitializer (const char* Name, int ZP) +void SymInitializer (const char* Name, unsigned InitVal) /* 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. + * an export. Initializers may never be zero page symbols. */ { SymEntry* S; - /* Check the ZP parameter */ - CHECK (ZP == 0); + /* Check the InitVal parameter */ + CHECK (InitVal >= EXP_INIT_MIN && InitVal <= EXP_INIT_MAX); /* Don't accept local symbols */ if (IsLocal (Name)) { @@ -600,20 +599,30 @@ void SymInitializer (const char* Name, int ZP) 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 an initializer, check if the new + * initializer value is the same as the old one. + */ + if (S->Flags & SF_INITIALIZER) { + if (S->InitVal != InitVal) { + Error (ERR_SYM_REDECL_MISMATCH); + } + } + S->InitVal = InitVal; + /* Set the symbol data */ S->Flags |= SF_EXPORT | SF_INITIALIZER | SF_REFERENCED; } @@ -634,7 +643,7 @@ int SymIsRef (const char* Name) { SymEntry* S = SymFindAny (SymTab, Name); return S != 0 && (S->Flags & SF_REFERENCED) != 0; -} +} @@ -1079,7 +1088,7 @@ void WriteExports (void) /* Add the initializer bits */ if (S->Flags & SF_INITIALIZER) { - ExprMask |= EXP_INIT; + ExprMask |= S->InitVal; } /* Write the type */ @@ -1151,7 +1160,7 @@ void WriteDbgSyms (void) /* Add the initializer bits */ if (S->Flags & SF_INITIALIZER) { - ExprMask |= EXP_INIT; + ExprMask |= S->InitVal; } /* Write the type */ diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 6c5642b27..959bc3a0c 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -86,12 +86,9 @@ void SymGlobal (const char* Name, int ZP); * either imported or exported. */ -void SymInitializer (const char* Name, int ZP); +void SymInitializer (const char* Name, unsigned InitVal); /* 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. + * an export. Initializers may never be zero page symbols. */ int SymIsConst (SymEntry* Sym); diff --git a/src/common/symdefs.h b/src/common/symdefs.h index 69a42f024..f4e192bf5 100644 --- a/src/common/symdefs.h +++ b/src/common/symdefs.h @@ -49,34 +49,37 @@ /* Import size */ -#define IMP_ABS 0x00 /* Import as normal value */ -#define IMP_ZP 0x01 /* Import as zero page symbol */ -#define IMP_MASK_SIZE 0x01 /* Size mask */ +#define IMP_ABS 0x00 /* Import as normal value */ +#define IMP_ZP 0x01 /* Import as zero page symbol */ +#define IMP_MASK_SIZE 0x01 /* Size mask */ -#define IS_IMP_ABS(x) (((x) & IMP_MASK_SIZE) == IMP_ABS) -#define IS_IMP_ZP(x) (((x) & IMP_MASK_SIZE) == IMP_ZP) +#define IS_IMP_ABS(x) (((x) & IMP_MASK_SIZE) == IMP_ABS) +#define IS_IMP_ZP(x) (((x) & IMP_MASK_SIZE) == IMP_ZP) /* Export size */ -#define EXP_ABS 0x00 /* Export as normal value */ -#define EXP_ZP 0x01 /* Export as zero page value */ -#define EXP_MASK_SIZE 0x01 /* Size mask */ +#define EXP_ABS 0x00 /* Export as normal value */ +#define EXP_ZP 0x20 /* Export as zero page value */ +#define EXP_MASK_SIZE 0x20 /* Size mask */ #define IS_EXP_ABS(x) (((x) & EXP_MASK_SIZE) == EXP_ABS) -#define IS_EXP_ZP(x) (((x) & EXP_MASK_SIZE) == EXP_ZP) +#define IS_EXP_ZP(x) (((x) & EXP_MASK_SIZE) == EXP_ZP) /* Export value type */ -#define EXP_CONST 0x00 /* Mask bit for const values */ -#define EXP_EXPR 0x02 /* Mask bit for expr values */ -#define EXP_MASK_VAL 0x02 /* Value mask */ +#define EXP_CONST 0x00 /* Mask bit for const values */ +#define EXP_EXPR 0x40 /* Mask bit for expr values */ +#define EXP_MASK_VAL 0x40 /* Value mask */ #define IS_EXP_CONST(x) (((x) & EXP_MASK_VAL) == EXP_CONST) #define IS_EXP_EXPR(x) (((x) & EXP_MASK_VAL) == EXP_EXPR) /* Export initializer flag */ -#define EXP_INIT 0x04 /* Mask bit for initializer export */ -#define EXP_MASK_INIT 0x04 /* Value mask */ +#define EXP_INIT_MIN 0x01 /* Minimum value */ +#define EXP_INIT_MAX 0x1F /* Maximum value */ +#define EXP_INIT_DEF 0x18 /* Default value */ +#define EXP_MASK_INIT 0x1F /* Initializer value mask */ -#define IS_EXP_INIT(x) (((x) & EXP_MASK_INIT) == EXP_INIT) +#define IS_EXP_INIT(x) (((x) & EXP_MASK_INIT) != 0) +#define GET_EXP_INIT_VAL(x) ((x) & EXP_MASK_INIT) diff --git a/src/ld65/dbgsyms.c b/src/ld65/dbgsyms.c index 5c649ce76..413f6cfa8 100644 --- a/src/ld65/dbgsyms.c +++ b/src/ld65/dbgsyms.c @@ -151,7 +151,7 @@ DbgSym* ReadDbgSym (FILE* F, ObjData* O) D->Name = ReadStr (F); /* Read the value */ - if (Type & EXP_EXPR) { + if (IS_EXP_EXPR (Type)) { D->Expr = ReadExpr (F, O); } else { D->Expr = LiteralExpr (Read32 (F), O); diff --git a/src/ld65/exports.c b/src/ld65/exports.c index 8f0427a6d..971db1558 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -39,6 +39,7 @@ /* common */ #include "check.h" +#include "coll.h" #include "hashstr.h" #include "symdefs.h" #include "xmalloc.h" @@ -54,25 +55,28 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ /* Hash table */ -#define HASHTAB_SIZE 4081 -static Export* HashTab [HASHTAB_SIZE]; +#define HASHTAB_SIZE 4081 +static Export* HashTab [HASHTAB_SIZE]; /* Import management variables */ -static unsigned ImpCount = 0; /* Import count */ -static unsigned ImpOpen = 0; /* Count of open imports */ +static unsigned ImpCount = 0; /* Import count */ +static unsigned ImpOpen = 0; /* Count of open imports */ /* Export management variables */ -static unsigned ExpCount = 0; /* Export count */ -static Export** ExpPool = 0; /* Exports array */ +static unsigned ExpCount = 0; /* Export count */ +static Export** ExpPool = 0; /* Exports array */ /* Defines for the flags in Export */ -#define EXP_USERMARK 0x0001 +#define EXP_USERMARK 0x0001 + +/* List of all exports that are also initializers */ +static Collection Initializers = STATIC_COLLECTION_INITIALIZER; @@ -227,6 +231,11 @@ void InsertExport (Export* E) Import* Imp; unsigned HashVal; + /* If this is an initializer, insert it into the initializer list */ + if (IS_EXP_INIT (E->Type)) { + CollAppend (&Initializers, E); + } + /* Create a hash value for the given name */ HashVal = HashStr (E->Name) % HASHTAB_SIZE; @@ -242,7 +251,7 @@ void InsertExport (Export* E) do { if (strcmp (L->Name, E->Name) == 0) { /* This may be an unresolved external */ - if (L->Expr == 0) { + if (L->Expr == 0) { /* This *is* an unresolved external */ E->Next = L->Next; @@ -298,7 +307,7 @@ Export* ReadExport (FILE* F, ObjData* O) E->Name = ReadStr (F); /* Read the value */ - if (Type & EXP_EXPR) { + if (IS_EXP_EXPR (Type)) { E->Expr = ReadExpr (F, O); } else { E->Expr = LiteralExpr (Read32 (F), O); @@ -408,18 +417,18 @@ long GetExportVal (const Export* E) -static void CheckSymType (Export* E) +static void CheckSymType (const Export* E) /* Check the types for one export */ { /* External with matching imports */ Import* Imp = E->ImpList; - int ZP = (E->Type & EXP_ZP) != 0; + int ZP = IS_EXP_ZP (E->Type); while (Imp) { - if (ZP != ((Imp->Type & IMP_ZP) != 0)) { + if (ZP != IS_IMP_ZP (Imp->Type)) { /* Export is ZP, import is abs or the other way round */ if (E->Obj) { - /* User defined export */ - Warning ("Type mismatch for `%s', export in " + /* User defined export */ + Warning ("Type mismatch for `%s', export in " "%s(%lu), import in %s(%lu)", E->Name, E->Obj->Files [Imp->Pos.Name], E->Pos.Line, Imp->Obj->Files [Imp->Pos.Name], @@ -444,7 +453,7 @@ static void CheckSymTypes (void) /* Print all open imports */ for (I = 0; I < ExpCount; ++I) { - Export* E = ExpPool [I]; + const Export* E = ExpPool [I]; if (E->Expr != 0 && E->ImpCount > 0) { /* External with matching imports */ CheckSymType (E); @@ -545,19 +554,20 @@ void PrintExportMap (FILE* F) /* Print all exports */ Count = 0; for (I = 0; I < ExpCount; ++I) { - Export* E = ExpPool [I]; + const Export* E = ExpPool [I]; /* Print unreferenced symbols only if explictly requested */ if (VerboseMap || E->ImpCount > 0) { fprintf (F, - "%-25s %06lX %c%c ", - E->Name, - GetExportVal (E), - E->ImpCount? 'R' : ' ', - (E->Type & EXP_ZP)? 'Z' : ' '); + "%-25s %06lX %c%c%c ", + E->Name, + GetExportVal (E), + E->ImpCount? 'R' : ' ', + IS_EXP_ZP (E->Type)? 'Z' : ' ', + IS_EXP_INIT (E->Type)? 'I' : ' '); if (++Count == 2) { - Count = 0; - fprintf (F, "\n"); + Count = 0; + fprintf (F, "\n"); } } } @@ -570,13 +580,13 @@ void PrintImportMap (FILE* F) /* Print an import map to the given file */ { unsigned I; - Import* Imp; + const Import* Imp; /* Loop over all exports */ for (I = 0; I < ExpCount; ++I) { /* Get the export */ - Export* Exp = ExpPool [I]; + const Export* Exp = ExpPool [I]; /* Print the symbol only if there are imports, or if a verbose map * file is requested. @@ -591,23 +601,23 @@ void PrintImportMap (FILE* F) /* Print the export */ fprintf (F, - "%s (%s):\n", - Exp->Name, - ObjName); + "%s (%s):\n", + Exp->Name, + ObjName); /* Print all imports for this symbol */ Imp = Exp->ImpList; while (Imp) { - /* Print the import */ - fprintf (F, - " %-25s %s(%lu)\n", - Imp->Obj->Name, - Imp->Obj->Files [Imp->Pos.Name], - Imp->Pos.Line); + /* Print the import */ + fprintf (F, + " %-25s %s(%lu)\n", + Imp->Obj->Name, + Imp->Obj->Files [Imp->Pos.Name], + Imp->Pos.Line); - /* Next import */ - Imp = Imp->Next; + /* Next import */ + Imp = Imp->Next; } } } @@ -623,7 +633,7 @@ void PrintExportLabels (FILE* F) /* Print all exports */ for (I = 0; I < ExpCount; ++I) { - Export* E = ExpPool [I]; + const Export* E = ExpPool [I]; fprintf (F, "al %06lX .%s\n", GetExportVal (E), E->Name); } } diff --git a/src/od65/dump.c b/src/od65/dump.c index 19016fa41..f5b880bda 100644 --- a/src/od65/dump.c +++ b/src/od65/dump.c @@ -213,7 +213,7 @@ static const char* GetExportFlags (unsigned Flags) case EXP_EXPR: strcat (TypeDesc, ",EXP_EXPR"); break; } if (IS_EXP_INIT (Flags)) { - strcat (TypeDesc, ",EXP_INIT"); + sprintf (TypeDesc+strlen(TypeDesc), ",EXP_INIT=%u", GET_EXP_INIT_VAL(Flags)); } /* Return the result */ -- 2.39.5