diff --git a/src/ar65/objfile.c b/src/ar65/objfile.c index 1f5bd8abe..6fb40f9af 100644 --- a/src/ar65/objfile.c +++ b/src/ar65/objfile.c @@ -286,6 +286,3 @@ void ObjExtract (const char* Name) - - - diff --git a/src/ca65/dbginfo.c b/src/ca65/dbginfo.c index 33362aca3..90b25c218 100644 --- a/src/ca65/dbginfo.c +++ b/src/ca65/dbginfo.c @@ -33,6 +33,8 @@ +#include + /* ca65 */ #include "error.h" #include "expr.h" diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 4ada4317a..3e09dee13 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -33,6 +33,8 @@ +#include + /* common */ #include "check.h" #include "exprdefs.h" diff --git a/src/ca65/filetab.c b/src/ca65/filetab.c index 8448d44df..4e1d28c44 100644 --- a/src/ca65/filetab.c +++ b/src/ca65/filetab.c @@ -33,6 +33,8 @@ +#include + /* common */ #include "check.h" #include "hashstr.h" diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index f460cdc91..5de8b9cb6 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -34,10 +34,11 @@ #include +#include /* common */ #include "check.h" - + /* ca65 */ #include "error.h" #include "expr.h" diff --git a/src/ca65/options.c b/src/ca65/options.c index ed1bd2405..31e37421e 100644 --- a/src/ca65/options.c +++ b/src/ca65/options.c @@ -33,6 +33,8 @@ +#include + /* common */ #include "optdefs.h" #include "xmalloc.h" diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 9373ec01b..cbc23b721 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -41,6 +41,7 @@ /* common */ #include "bitops.h" +#include "cddefs.h" #include "check.h" #include "symdefs.h" #include "tgttrans.h" @@ -173,6 +174,32 @@ static long IntArg (long Min, long Max) +static void ConDes (const char* Name, unsigned Type) +/* Parse remaining line for constructor/destructor of the remaining type */ +{ + long Prio; + + /* Optional constructor priority */ + if (Tok == TOK_COMMA) { + /* Priority value follows */ + NextTok (); + Prio = ConstExpression (); + if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) { + /* Value out of range */ + Error (ERR_RANGE); + return; + } + } else { + /* Use the default priority value */ + Prio = CD_PRIO_DEF; + } + + /* Define the symbol */ + SymConDes (Name, Type, (unsigned) Prio); +} + + + /*****************************************************************************/ /* Handler functions */ /*****************************************************************************/ @@ -320,7 +347,7 @@ static void DoByte (void) NextTok (); /* Do smart handling of dangling comma */ if (Tok == TOK_SEP) { - Error (ERR_UNEXPECTED_EOL); + Error (ERR_UNEXPECTED_EOL); break; } } @@ -346,6 +373,76 @@ static void DoCode (void) +static void DoConDes (void) +/* Export a symbol as constructor/destructor */ +{ + static const char* Keys[] = { + "CONSTRUCTOR", + "DESTRUCTOR", + }; + char Name [sizeof (SVal)]; + long Type; + + /* Symbol name follows */ + if (Tok != TOK_IDENT) { + ErrorSkip (ERR_IDENT_EXPECTED); + return; + } + strcpy (Name, SVal); + NextTok (); + + /* Type follows. May be encoded as identifier or numerical */ + ConsumeComma (); + if (Tok == TOK_IDENT) { + + /* Map the following keyword to a number, then skip it */ + Type = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0])); + NextTok (); + + /* Check if we got a valid keyword */ + if (Type < 0) { + Error (ERR_SYNTAX); + SkipUntilSep (); + return; + } + + } else { + + /* Read the type as numerical value */ + Type = ConstExpression (); + if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) { + /* Value out of range */ + Error (ERR_RANGE); + return; + } + + } + + /* Parse the remainder of the line and export the symbol */ + ConDes (Name, (unsigned) Type); +} + + + +static void DoConstructor (void) +/* Export a symbol as constructor */ +{ + char Name [sizeof (SVal)]; + + /* Symbol name follows */ + if (Tok != TOK_IDENT) { + ErrorSkip (ERR_IDENT_EXPECTED); + return; + } + strcpy (Name, SVal); + NextTok (); + + /* Parse the remainder of the line and export the symbol */ + ConDes (Name, CD_TYPE_CON); +} + + + static void DoData (void) /* Switch to the data segment */ { @@ -422,6 +519,25 @@ static void DoDefine (void) +static void DoDestructor (void) +/* Export a symbol as destructor */ +{ + char Name [sizeof (SVal)]; + + /* Symbol name follows */ + if (Tok != TOK_IDENT) { + ErrorSkip (ERR_IDENT_EXPECTED); + return; + } + strcpy (Name, SVal); + NextTok (); + + /* Parse the remainder of the line and export the symbol */ + ConDes (Name, CD_TYPE_DES); +} + + + static void DoDWord (void) /* Define dwords */ { @@ -736,41 +852,6 @@ static void DoInclude (void) -static void DoInitializer (void) -/* Export a symbol as initializer */ -{ - 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); -} - - - static void DoInvalid (void) /* Handle a token that is invalid here, since it should have been handled on * a much lower level of the expression hierarchy. Getting this sort of token @@ -1171,7 +1252,9 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoCase }, { ccNone, DoCode }, { ccNone, DoUnexpected, }, /* .CONCAT */ + { ccNone, DoConDes }, { ccNone, DoUnexpected }, /* .CONST */ + { ccNone, DoConstructor }, { ccNone, DoUnexpected }, /* .CPU */ { ccNone, DoData }, { ccNone, DoDbg, }, @@ -1179,6 +1262,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoDebugInfo }, { ccNone, DoDefine }, { ccNone, DoUnexpected }, /* .DEFINED */ + { ccNone, DoDestructor }, { ccNone, DoDWord }, { ccKeepToken, DoConditionals }, /* .ELSE */ { ccKeepToken, DoConditionals }, /* .ELSEIF */ @@ -1215,7 +1299,6 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoImportZP }, { ccNone, DoIncBin }, { ccNone, DoInclude }, - { ccNone, DoInitializer }, { ccNone, DoInvalid }, /* .LEFT */ { ccNone, DoLineCont }, { ccNone, DoList }, diff --git a/src/ca65/repeat.c b/src/ca65/repeat.c index b442c165f..d2a0de67a 100644 --- a/src/ca65/repeat.c +++ b/src/ca65/repeat.c @@ -33,6 +33,8 @@ +#include + /* common */ #include "xmalloc.h" @@ -106,7 +108,7 @@ static void RepeatTokenCheck (TokList* L) /* Called each time a token from a repeat token list is set. Is used to check * for and replace identifiers that are the repeat counter. */ -{ +{ if (Tok == TOK_IDENT && L->Data != 0 && strcmp (SVal, L->Data) == 0) { /* Must replace by the repeat counter */ Tok = TOK_INTCON; diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index b14a974d6..7fb2fe97c 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -133,7 +133,9 @@ struct DotKeyword { { "CASE", TOK_CASE }, { "CODE", TOK_CODE }, { "CONCAT", TOK_CONCAT }, + { "CONDES", TOK_CONDES }, { "CONST", TOK_CONST }, + { "CONSTRUCTOR", TOK_CONSTRUCTOR }, { "CPU", TOK_CPU }, { "DATA", TOK_DATA }, { "DBG", TOK_DBG }, @@ -142,6 +144,7 @@ struct DotKeyword { { "DEF", TOK_DEFINED }, { "DEFINE", TOK_DEFINE }, { "DEFINED", TOK_DEFINED }, + { "DESTRUCTOR", TOK_DESTRUCTOR }, { "DWORD", TOK_DWORD }, { "ELSE", TOK_ELSE }, { "ELSEIF", TOK_ELSEIF }, @@ -182,7 +185,6 @@ struct DotKeyword { { "IMPORTZP", TOK_IMPORTZP }, { "INCBIN", TOK_INCBIN }, { "INCLUDE", TOK_INCLUDE }, - { "INITIALIZER", TOK_INITIALIZER }, { "LEFT", TOK_LEFT }, { "LINECONT", TOK_LINECONT }, { "LIST", TOK_LIST }, diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index 0849eb529..f6fddc588 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -120,8 +120,10 @@ enum Token { TOK_BYTE, TOK_CASE, TOK_CODE, - TOK_CONCAT, + TOK_CONCAT, + TOK_CONDES, TOK_CONST, + TOK_CONSTRUCTOR, TOK_CPU, TOK_DATA, TOK_DBG, @@ -129,6 +131,7 @@ enum Token { TOK_DEBUGINFO, TOK_DEFINE, TOK_DEFINED, + TOK_DESTRUCTOR, TOK_DWORD, TOK_ELSE, TOK_ELSEIF, @@ -165,7 +168,6 @@ enum Token { TOK_IMPORTZP, TOK_INCBIN, TOK_INCLUDE, - TOK_INITIALIZER, TOK_LEFT, TOK_LINECONT, TOK_LIST, diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index 8c2af8671..76055f927 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -36,6 +36,7 @@ #include /* common */ +#include "cddefs.h" #include "check.h" #include "hashstr.h" #include "symdefs.h" @@ -63,9 +64,8 @@ #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_INDEXED 0x0800 /* Index is valid */ #define SF_CONST 0x1000 /* The symbol has a constant value */ #define SF_MULTDEF 0x2000 /* Multiply defined symbol */ @@ -97,15 +97,16 @@ struct SymEntry { long Val; /* Value (if CONST set) */ SymEntry* Sym; /* Symbol (if trampoline entry) */ } V; - unsigned char InitVal; /* Initializer value */ + 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 +#define MAIN_HASHTAB_SIZE 213 +#define SUB_HASHTAB_SIZE 53 typedef struct SymTable SymTable; struct SymTable { unsigned TableSlots; /* Number of hash table slots */ @@ -140,7 +141,7 @@ static unsigned ExportCount = 0;/* Counter for export symbols */ static int IsLocal (const char* Name) /* Return true if Name is the name of a local symbol */ -{ +{ return (*Name == LocalStart); } @@ -166,7 +167,7 @@ static SymEntry* NewSymEntry (const char* Name) S->Pos = CurPos; S->Flags = 0; S->V.Expr = 0; - S->InitVal = 0; + memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio)); memcpy (S->Name, Name, Len+1); /* Insert it into the list of all entries */ @@ -579,15 +580,16 @@ void SymGlobal (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. +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 InitVal parameter */ - CHECK (InitVal >= EXP_INIT_MIN && InitVal <= EXP_INIT_MAX); + /* Check the parameters */ + CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX); + CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX); /* Don't accept local symbols */ if (IsLocal (Name)) { @@ -613,18 +615,18 @@ void SymInitializer (const char* Name, unsigned InitVal) 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 the symbol was already declared as a condes, check if the new + * priority value is the same as the old one. */ - if (S->Flags & SF_INITIALIZER) { - if (S->InitVal != InitVal) { + if (S->ConDesPrio[Type] != CD_PRIO_NONE) { + if (S->ConDesPrio[Type] != Prio) { Error (ERR_SYM_REDECL_MISMATCH); } } - S->InitVal = InitVal; + S->ConDesPrio[Type] = Prio; /* Set the symbol data */ - S->Flags |= SF_EXPORT | SF_INITIALIZER | SF_REFERENCED; + S->Flags |= SF_EXPORT | SF_REFERENCED; } @@ -1064,6 +1066,7 @@ 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 (); @@ -1086,14 +1089,26 @@ void WriteExports (void) /* Add zeropage/abs bits */ ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS; - /* Add the initializer bits */ - if (S->Flags & SF_INITIALIZER) { - ExprMask |= S->InitVal; + /* 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); @@ -1158,11 +1173,6 @@ void WriteDbgSyms (void) /* Add zeropage/abs bits */ ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS; - /* Add the initializer bits */ - if (S->Flags & SF_INITIALIZER) { - ExprMask |= S->InitVal; - } - /* Write the type */ ObjWrite8 (ExprMask); diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 959bc3a0c..f25b2e09e 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -86,9 +86,9 @@ void SymGlobal (const char* Name, int ZP); * either imported or exported. */ -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. +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. */ int SymIsConst (SymEntry* Sym); diff --git a/src/cc65/asmline.c b/src/cc65/asmline.c index db8c16812..7303a82e3 100644 --- a/src/cc65/asmline.c +++ b/src/cc65/asmline.c @@ -34,10 +34,13 @@ #include - -#include "../common/xmalloc.h" -#include "../common/xsprintf.h" - +#include + +/* common */ +#include "xmalloc.h" +#include "xsprintf.h" + +/* cc65 */ #include "error.h" #include "asmline.h" diff --git a/src/cc65/declattr.c b/src/cc65/declattr.c index b06c36aed..9dbc71095 100644 --- a/src/cc65/declattr.c +++ b/src/cc65/declattr.c @@ -33,6 +33,8 @@ +#include + /* cc65 */ #include "error.h" #include "scanner.h" @@ -125,7 +127,7 @@ void ParseAttribute (const Declaration* D, DeclAttr* A) /* Parse an additional __attribute__ modifier */ { ident AttrName; - attrib_t AttrType; + attrib_t AttrType; /* Initialize the attribute description with "no attribute" */ A->AttrType = atNone; diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index f4020cf3b..c68009c02 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -34,8 +34,10 @@ #include +#include #include - + +/* cc65 */ #include "codegen.h" #include "error.h" #include "expr.h" diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index 03223fc97..35ed800b4 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -33,8 +33,12 @@ -#include "../common/xmalloc.h" - +#include + +/* common */ +#include "xmalloc.h" + +/* cc65 */ #include "symentry.h" @@ -43,7 +47,7 @@ /* Code */ /*****************************************************************************/ - + SymEntry* NewSymEntry (const char* Name, unsigned Flags) /* Create a new symbol table with the given name */ diff --git a/src/ld65/initfunc.c b/src/common/cddefs.h similarity index 60% rename from src/ld65/initfunc.c rename to src/common/cddefs.h index 60ea52805..5d8717931 100644 --- a/src/ld65/initfunc.c +++ b/src/common/cddefs.h @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* initfunc.c */ +/* cddefs.h */ /* */ -/* Init/cleanup function handling */ +/* Definitions for module constructor/destructors */ /* */ /* */ /* */ -/* (C) 2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (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 */ @@ -33,47 +33,48 @@ -/* common */ -#include "coll.h" - -/* ld65 */ -#include "exports.h" -#include "segments.h" -#include "initfunc.h" +#ifndef CDDEFS_H +#define CDDEFS_H /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ -/* List of all exports that are also initializers/cleanup functions */ -static Collection InitFunctions = STATIC_COLLECTION_INITIALIZER; -static Collection CleanupFunctions = STATIC_COLLECTION_INITIALIZER; +/* ConDes types. Count is only 7 because we want to encode 0..count in 3 bits */ +#define CD_TYPE_COUNT 7 /* Number of table types */ +#define CD_TYPE_MIN 0 /* Minimum numeric type value */ +#define CD_TYPE_MAX 6 /* Maximum numeric type value */ + +/* ConDes priorities, zero is no valid priority and used to mark an empty + * (missing) decl for this type throughout the code. + */ +#define CD_PRIO_NONE 0 /* No priority (no decl) */ +#define CD_PRIO_MIN 1 /* Lowest priority */ +#define CD_PRIO_DEF 7 /* Default priority */ +#define CD_PRIO_MAX 32 /* Highest priority */ + +/* Predefined types */ +#define CD_TYPE_CON 0 /* Constructor */ +#define CD_TYPE_DES 1 /* Destructor */ + +/* When part of an export in an object file, type and priority are encoded in + * one byte. In this case, the following macros access the fields: + */ +#define CD_GET_TYPE(v) (((v) >> 5) & 0x07) +#define CD_GET_PRIO(v) (((v) & 0x1F) + 1) + +/* Macro to build the byte value: */ +#define CD_BUILD(type,prio) ((((type) & 0x07) << 5) | (((prio) - 1) & 0x1F)) -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ - - - -void AddInitFunc (Export* E) -/* Add the given export to the list of initializers */ -{ - CollAppend (&InitFunctions, E); -} - - - -void AddCleanupFunc (Export* E) -/* Add the given export to the list of cleanup functions */ -{ - CollAppend (&CleanupFunctions, E); -} +/* End of cddefs.h */ + +#endif diff --git a/src/common/coll.c b/src/common/coll.c index 8ce56a8c7..d6929f707 100644 --- a/src/common/coll.c +++ b/src/common/coll.c @@ -225,14 +225,64 @@ void CollReplace (Collection* C, void* Item, unsigned Index) -void CollSort (Collection* C, int (*Compare) (const void*, const void*)) -/* Sort the collection using the given compare function. - * BEWARE: The function uses qsort internally, so the Compare function does - * actually get pointers to the object pointers, not just object pointers! - */ +static void QuickSort (Collection* C, int Lo, int Hi, + int (*Compare) (void*, const void*, const void*), + void* Data) +/* Internal recursive sort function. */ { - /* Use qsort */ - qsort (C->Items, C->Count, sizeof (void*), Compare); + /* Get a pointer to the items */ + void** Items = C->Items; + + /* Quicksort */ + while (Hi > Lo) { + int I = Lo + 1; + int J = Hi; + while (I <= J) { + while (I <= J && Compare (Data, Items[Lo], Items[I]) >= 0) { + ++I; + } + while (I <= J && Compare (Data, Items[Lo], Items[J]) < 0) { + --J; + } + if (I <= J) { + /* Swap I and J */ + void* Tmp = Items[I]; + Items[I] = Items[J]; + Items[J] = Tmp; + ++I; + --J; + } + } + if (J != Lo) { + /* Swap J and Lo */ + void* Tmp = Items[J]; + Items[J] = Items[Lo]; + Items[Lo] = Tmp; + } + if (J > (Hi + Lo) / 2) { + QuickSort (C, J + 1, Hi, Compare, Data); + Hi = J - 1; + } else { + QuickSort (C, Lo, J - 1, Compare, Data); + Lo = J + 1; + } + } +} + + + +void CollSort (Collection* C, + int (*Compare) (void*, const void*, const void*), + void* Data) +/* Sort the collection using the given compare function. The data pointer is + * passed as *first* element to the compare function, it's not used by the + * sort function itself. The other two pointer passed to the Compare function + * are pointers to objects. + */ +{ + if (C->Count > 1) { + QuickSort (C, 0, C->Count-1, Compare, Data); + } } diff --git a/src/common/coll.h b/src/common/coll.h index 144442f65..ba1d4f601 100644 --- a/src/common/coll.h +++ b/src/common/coll.h @@ -113,10 +113,13 @@ void CollReplace (Collection* C, void* Item, unsigned Index); * just the pointer will et replaced. */ -void CollSort (Collection* C, int (*Compare) (const void*, const void*)); -/* Sort the collection using the given compare function. - * BEWARE: The function uses qsort internally, so the Compare function does - * actually get pointers to the object pointers, not just object pointers! +void CollSort (Collection* C, + int (*Compare) (void*, const void*, const void*), + void* Data); +/* Sort the collection using the given compare function. The data pointer is + * passed as *first* element to the compare function, it's not used by the + * sort function itself. The other two pointer passed to the Compare function + * are pointers to objects. */ diff --git a/src/common/objdefs.h b/src/common/objdefs.h index 8ea626deb..7678f4763 100644 --- a/src/common/objdefs.h +++ b/src/common/objdefs.h @@ -46,7 +46,7 @@ /* Defines for magic and version */ #define OBJ_MAGIC 0x616E7A55 -#define OBJ_VERSION 0x0007 +#define OBJ_VERSION 0x0008 /* Size of an object file header */ #define OBJ_HDR_SIZE 56 diff --git a/src/common/symdefs.h b/src/common/symdefs.h index f4e192bf5..bf5ebe284 100644 --- a/src/common/symdefs.h +++ b/src/common/symdefs.h @@ -58,28 +58,26 @@ /* Export size */ #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 EXP_ZP 0x08 /* Export as zero page value */ +#define EXP_MASK_SIZE 0x08 /* Size mask */ #define IS_EXP_ABS(x) (((x) & EXP_MASK_SIZE) == EXP_ABS) #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 0x40 /* Mask bit for expr values */ -#define EXP_MASK_VAL 0x40 /* Value mask */ +#define EXP_EXPR 0x10 /* Mask bit for expr values */ +#define EXP_MASK_VAL 0x10 /* 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_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 */ +/* Number of module constructor/destructor declarations for an export */ +#define EXP_CONDES_MASK 0x07 -#define IS_EXP_INIT(x) (((x) & EXP_MASK_INIT) != 0) -#define GET_EXP_INIT_VAL(x) ((x) & EXP_MASK_INIT) +#define IS_EXP_CONDES(x) (((x) & EXP_CONDES_MASK) != 0) +#define GET_EXP_CONDES_COUNT(x) ((x) & EXP_CONDES_MASK) +#define INC_EXP_CONDES_COUNT(x) ((x)++) diff --git a/src/common/target.c b/src/common/target.c index 74864d243..3a5fc2171 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -34,6 +34,7 @@ #include +#include #include #include "target.h" diff --git a/src/da65/config.c b/src/da65/config.c index d76aa6993..275ba7d50 100644 --- a/src/da65/config.c +++ b/src/da65/config.c @@ -34,6 +34,7 @@ #include +#include #if defined(_MSC_VER) /* Microsoft compiler */ # include diff --git a/src/ld65/condes.c b/src/ld65/condes.c new file mode 100644 index 000000000..7c9e7f73b --- /dev/null +++ b/src/ld65/condes.c @@ -0,0 +1,188 @@ +/*****************************************************************************/ +/* */ +/* condes.h */ +/* */ +/* Module constructor/destructor support */ +/* */ +/* */ +/* */ +/* (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. */ +/* */ +/*****************************************************************************/ + + + +/* common */ +#include "check.h" +#include "coll.h" +#include "xmalloc.h" + +/* ld65 */ +#include "exports.h" +#include "segments.h" +#include "condes.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Struct describing one condes type */ +typedef struct ConDesDesc ConDesDesc; +struct ConDesDesc { + Collection ExpList; /* List of exported symbols */ + char* Label; /* Name of table label */ + char* SegName; /* Name of segment the table is in */ + unsigned char Enable; /* Table enabled */ +}; + +/* Array for all types */ +static ConDesDesc ConDes[CD_TYPE_COUNT] = { + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, + { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 }, +}; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +void ConDesAddExport (struct Export* E) +/* Add the given export to the list of constructors/destructor */ +{ + unsigned Type; + + /* Insert the export into all tables for which declarations exist */ + for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { + unsigned Prio = E->ConDes[Type]; + if (Prio != CD_PRIO_NONE) { + CollAppend (&ConDes[Type].ExpList, E); + } + } +} + + + +void ConDesSetSegName (unsigned Type, const char* SegName) +/* Set the segment name where the table should go */ +{ + /* Check the parameters */ + PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && SegName != 0); + + /* Setting the segment name twice is bad */ + CHECK (ConDes[Type].SegName == 0); + + /* Set the name */ + ConDes[Type].SegName = xstrdup (SegName); +} + + + +void ConDesSetLabel (unsigned Type, const char* Name) +/* Set the label for the given ConDes type */ +{ + /* Check the parameters */ + PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && Name != 0); + + /* Setting the label twice is bad */ + CHECK (ConDes[Type].Label == 0); + + /* Set the name */ + ConDes[Type].Label = xstrdup (Name); +} + + + +const char* ConDesGetSegName (unsigned Type) +/* Return the segment name for the given ConDes type */ +{ + /* Check the parameters */ + PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX); + + /* Return the name */ + return ConDes[Type].SegName; +} + + + +const char* ConDesGetLabel (unsigned Type) +/* Return the label for the given ConDes type */ +{ + /* Check the parameters */ + PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX); + + /* Return the name */ + return ConDes[Type].Label; +} + + + +int ConDesHasSegName (unsigned Type) +/* Return true if a segment name is already defined for this ConDes type */ +{ + return (ConDesGetSegName(Type) != 0); +} + + + +int ConDesHasLabel (unsigned Type) +/* Return true if a label is already defined for this ConDes type */ +{ + return (ConDesGetLabel(Type) != 0); +} + + + +void ConDesCreate (void) +/* Create the condes tables if requested */ +{ +} + + + +void ConDesDump (void) +/* Dump ConDes data to stdout for debugging */ +{ + unsigned Type; + for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { + Collection* ExpList = &ConDes[Type].ExpList; + printf ("CONDES(%u): %u symbols\n", Type, CollCount (ExpList)); + } +} + + + + + diff --git a/src/ld65/initfunc.h b/src/ld65/condes.h similarity index 72% rename from src/ld65/initfunc.h rename to src/ld65/condes.h index fef48e11a..72d295acd 100644 --- a/src/ld65/initfunc.h +++ b/src/ld65/condes.h @@ -1,8 +1,8 @@ /*****************************************************************************/ /* */ -/* initfunc.h */ +/* condes.h */ /* */ -/* Init/cleanup function handling */ +/* Module constructor/destructor support */ /* */ /* */ /* */ @@ -33,13 +33,13 @@ -#ifndef INITFUNC_H -#define INITFUNC_H +#ifndef CONDES_H +#define CONDES_H /*****************************************************************************/ -/* Forwards */ +/* Forwards */ /*****************************************************************************/ @@ -54,15 +54,36 @@ struct Export; -void AddInitFunc (struct Export* E); -/* Add the given export to the list of initializers */ +void ConDesAddExport (struct Export* E); +/* Add the given export to the list of constructors/destructor */ -void AddCleanupFunc (struct Export* E); -/* Add the given export to the list of cleanup functions */ +void ConDesSetSegName (unsigned Type, const char* SegName); +/* Set the segment name where the table should go */ + +void ConDesSetLabel (unsigned Type, const char* Name); +/* Set the label for the given ConDes type */ + +const char* ConDesGetSegName (unsigned Type); +/* Return the segment name for the given ConDes type */ + +const char* ConDesGetLabel (unsigned Type); +/* Return the label for the given ConDes type */ + +int ConDesHasSegName (unsigned Type); +/* Return true if a segment name is already defined for this ConDes type */ + +int ConDesHasLabel (unsigned Type); +/* Return true if a label is already defined for this ConDes type */ + +void ConDesCreate (void); +/* Create the condes tables if requested */ + +void ConDesDump (void); +/* Dump ConDes data to stdout for debugging */ -/* End of initfunc.h */ +/* End of condes.h */ #endif diff --git a/src/ld65/config.c b/src/ld65/config.c index d3f637654..314fc235c 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -42,14 +42,15 @@ #include "check.h" #include "bitops.h" #include "xmalloc.h" - + /* ld65 */ -#include "error.h" -#include "global.h" #include "bin.h" -#include "o65.h" #include "binfmt.h" +#include "condes.h" +#include "error.h" #include "exports.h" +#include "global.h" +#include "o65.h" #include "scanner.h" #include "config.h" @@ -115,6 +116,141 @@ static unsigned O65Attr = 0; +/*****************************************************************************/ +/* Forwards */ +/*****************************************************************************/ + + + +static File* NewFile (const char* Name); +/* Create a new file descriptor and insert it into the list */ + + + +/*****************************************************************************/ +/* List management */ +/*****************************************************************************/ + + + +static File* FindFile (const char* Name) +/* Find a file with a given name. */ +{ + File* F = FileList; + while (F) { + if (strcmp (F->Name, Name) == 0) { + return F; + } + F = F->Next; + } + return 0; +} + + + +static File* GetFile (const char* Name) +/* Get a file entry with the given name. Create a new one if needed. */ +{ + File* F = FindFile (Name); + if (F == 0) { + /* Create a new one */ + F = NewFile (Name); + } + return F; +} + + + +static void FileInsert (File* F, Memory* M) +/* Insert the memory area into the files list */ +{ + M->F = F; + if (F->MemList == 0) { + /* First entry */ + F->MemList = M; + } else { + F->MemLast->FNext = M; + } + F->MemLast = M; +} + + + +static Memory* CfgFindMemory (const char* Name) +/* Find the memory are with the given name. Return NULL if not found */ +{ + Memory* M = MemoryList; + while (M) { + if (strcmp (M->Name, Name) == 0) { + return M; + } + M = M->Next; + } + return 0; +} + + + +static Memory* CfgGetMemory (const char* Name) +/* Find the memory are with the given name. Print an error on an invalid name */ +{ + Memory* M = CfgFindMemory (Name); + if (M == 0) { + CfgError ("Invalid memory area `%s'", Name); + } + return M; +} + + + +static SegDesc* CfgFindSegDesc (const char* Name) +/* Find the segment descriptor with the given name, return NULL if not found. */ +{ + SegDesc* S = SegDescList; + while (S) { + if (strcmp (S->Name, Name) == 0) { + /* Found */ + return S; + } + S = S->Next; + } + + /* Not found */ + return 0; +} + + + +static void SegDescInsert (SegDesc* S) +/* Insert a segment descriptor into the list of segment descriptors */ +{ + /* Insert the struct into the list */ + S->Next = SegDescList; + SegDescList = S; + ++SegDescCount; +} + + + +static void MemoryInsert (Memory* M, SegDesc* S) +/* Insert the segment descriptor into the memory area list */ +{ + /* Create a new node for the entry */ + MemListNode* N = xmalloc (sizeof (MemListNode)); + N->Seg = S; + N->Next = 0; + + if (M->SegLast == 0) { + /* First entry */ + M->SegList = N; + } else { + M->SegLast->Next = N; + } + M->SegLast = N; +} + + + /*****************************************************************************/ /* Constructors/Destructors */ /*****************************************************************************/ @@ -156,13 +292,9 @@ static Memory* NewMemory (const char* Name) unsigned Len = strlen (Name); /* Check for duplicate names */ - Memory* M = MemoryList; - while (M) { - if (strcmp (M->Name, Name) == 0) { - CfgError ("Memory area `%s' defined twice", Name); - break; - } - M = M->Next; + Memory* M = CfgFindMemory (Name); + if (M) { + CfgError ("Memory area `%s' defined twice", Name); } /* Allocate memory */ @@ -208,13 +340,9 @@ static SegDesc* NewSegDesc (const char* Name) unsigned Len = strlen (Name); /* Check for duplicate names */ - SegDesc* S = SegDescList; - while (S) { - if (strcmp (S->Name, Name) == 0) { - CfgError ("Segment `%s' defined twice", Name); - break; - } - S = S->Next; + SegDesc* S = CfgFindSegDesc (Name); + if (S) { + CfgError ("Segment `%s' defined twice", Name); } /* Verify that the given segment does really exist */ @@ -278,49 +406,6 @@ static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name) -static File* FindFile (const char* Name) -/* Find a file with a given name. */ -{ - File* F = FileList; - while (F) { - if (strcmp (F->Name, Name) == 0) { - return F; - } - F = F->Next; - } - return 0; -} - - - -static File* GetFile (const char* Name) -/* Get a file entry with the given name. Create a new one if needed. */ -{ - File* F = FindFile (Name); - if (F == 0) { - /* Create a new one */ - F = NewFile (Name); - } - return F; -} - - - -static void FileInsert (File* F, Memory* M) -/* Insert the memory area into the files list */ -{ - M->F = F; - if (F->MemList == 0) { - /* First entry */ - F->MemList = M; - } else { - F->MemLast->FNext = M; - } - F->MemLast = M; -} - - - static void ParseMemory (void) /* Parse a MEMORY section */ { @@ -351,7 +436,7 @@ static void ParseMemory (void) while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ - unsigned AttrTok; + cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; @@ -477,7 +562,7 @@ static void ParseFiles (void) while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ - unsigned AttrTok; + cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; @@ -528,63 +613,6 @@ static void ParseFiles (void) -static Memory* CfgFindMemory (const char* Name) -/* Find the memory are with the given name. Return NULL if not found */ -{ - Memory* M = MemoryList; - while (M) { - if (strcmp (M->Name, Name) == 0) { - return M; - } - M = M->Next; - } - return 0; -} - - - -static Memory* CfgGetMemory (const char* Name) -/* Find the memory are with the given name. Print an error on an invalid name */ -{ - Memory* M = CfgFindMemory (Name); - if (M == 0) { - CfgError ("Invalid memory area `%s'", Name); - } - return M; -} - - - -static void SegDescInsert (SegDesc* S) -/* Insert a segment descriptor into the list of segment descriptors */ -{ - /* Insert the struct into the list */ - S->Next = SegDescList; - SegDescList = S; - ++SegDescCount; -} - - - -static void MemoryInsert (Memory* M, SegDesc* S) -/* Insert the segment descriptor into the memory area list */ -{ - /* Create a new node for the entry */ - MemListNode* N = xmalloc (sizeof (MemListNode)); - N->Seg = S; - N->Next = 0; - - if (M->SegLast == 0) { - /* First entry */ - M->SegList = N; - } else { - M->SegLast->Next = N; - } - M->SegLast = N; -} - - - static void ParseSegments (void) /* Parse a SEGMENTS section */ { @@ -623,7 +651,7 @@ static void ParseSegments (void) while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ - unsigned AttrTok; + cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; @@ -649,9 +677,11 @@ static void ParseSegments (void) CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { case CFGTOK_RO: S->Flags |= SF_RO; break; + case CFGTOK_RW: /* Default */ break; case CFGTOK_BSS: S->Flags |= SF_BSS; break; case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break; case CFGTOK_WPROT: S->Flags |= (SF_RO | SF_WPROT); break; + default: Internal ("Unexpected token: %d", CfgTok); } break; @@ -788,7 +818,7 @@ static void ParseO65 (void) while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ - unsigned AttrTok; + cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; @@ -843,7 +873,7 @@ static void ParseO65 (void) break; default: - Error ("Unexpected type token"); + CfgError ("Unexpected type token"); } break; @@ -863,7 +893,7 @@ static void ParseO65 (void) break; default: - Error ("Unexpected OS token"); + CfgError ("Unexpected OS token"); } break; @@ -892,7 +922,7 @@ static void ParseFormats (void) while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ - unsigned FormatTok; + cfgtok_t FormatTok; CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); FormatTok = CfgTok; @@ -922,16 +952,165 @@ static void ParseFormats (void) +static void ParseConDes (void) +/* Parse the CONDES feature */ +{ + static const IdentTok Attributes [] = { + { "SEGMENT", CFGTOK_SEGMENT }, + { "LABEL", CFGTOK_LABEL }, + { "TYPE", CFGTOK_TYPE }, + }; + + static const IdentTok Types [] = { + { "CONSTRUCTOR", CFGTOK_CONSTRUCTOR }, + { "DESTRUCTOR", CFGTOK_DESTRUCTOR }, + }; + + /* Attribute values. */ + char SegName[sizeof (CfgSVal)]; + char Label[sizeof (CfgSVal)]; + int Type = -1; /* Initialize to avoid gcc warnings */ + + /* Bitmask to remember the attributes we got already */ + enum { + atNone = 0x0000, + atSegName = 0x0001, + atLabel = 0x0002, + atType = 0x0004 + }; + unsigned AttrFlags = atNone; + + /* Parse the attributes */ + while (1) { + + /* Map the identifier to a token */ + cfgtok_t AttrTok; + CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); + AttrTok = CfgTok; + + /* An optional assignment follows */ + CfgNextTok (); + CfgOptionalAssign (); + + /* Check which attribute was given */ + switch (AttrTok) { + + case CFGTOK_SEGMENT: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atSegName, "SEGMENT"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + strcpy (SegName, CfgSVal); + break; + + case CFGTOK_LABEL: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atLabel, "LABEL"); + /* We expect an identifier */ + CfgAssureIdent (); + /* Remember the value for later */ + strcpy (Label, CfgSVal); + break; + + + case CFGTOK_TYPE: + /* Don't allow this twice */ + FlagAttr (&AttrFlags, atType, "TYPE"); + /* The type may be given as id or numerical */ + if (CfgTok == CFGTOK_INTCON) { + CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); + Type = (int) CfgIVal; + } else { + CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); + switch (CfgTok) { + case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; + case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; + default: FAIL ("Unexpected type token"); + } + } + break; + + default: + FAIL ("Unexpected attribute token"); + + } + + /* Skip the attribute value */ + CfgNextTok (); + + /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ + if (CfgTok == CFGTOK_SEMI) { + break; + } else if (CfgTok == CFGTOK_COMMA) { + CfgNextTok (); + } + } + + /* Check if we have all mandatory attributes */ + AttrCheck (AttrFlags, atSegName, "SEGMENT"); + AttrCheck (AttrFlags, atLabel, "LABEL"); + AttrCheck (AttrFlags, atType, "TYPE"); + + /* Check if the condes has already attributes defined */ + if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) { + CfgError ("CONDES attributes for type %d are already defined", Type); + } + + /* Define the attributes */ + ConDesSetSegName (Type, SegName); + ConDesSetLabel (Type, Label); +} + + + +static void ParseFeatures (void) +/* Parse a features section */ +{ + static const IdentTok Features [] = { + { "CONDES", CFGTOK_CONDES }, + }; + + while (CfgTok == CFGTOK_IDENT) { + + /* Map the identifier to a token */ + cfgtok_t FeatureTok; + CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature"); + FeatureTok = CfgTok; + + /* Skip the name and the following colon */ + CfgNextTok (); + CfgConsumeColon (); + + /* Parse the format options */ + switch (FeatureTok) { + + case CFGTOK_CONDES: + ParseConDes (); + break; + + default: + Error ("Unexpected feature token"); + } + + /* Skip the semicolon */ + CfgConsumeSemi (); + } +} + + + static void ParseConfig (void) /* Parse the config file */ { static const IdentTok BlockNames [] = { - { "MEMORY", CFGTOK_MEMORY }, - { "FILES", CFGTOK_FILES }, - { "SEGMENTS", CFGTOK_SEGMENTS }, - { "FORMATS", CFGTOK_FORMATS }, + { "MEMORY", CFGTOK_MEMORY }, + { "FILES", CFGTOK_FILES }, + { "SEGMENTS", CFGTOK_SEGMENTS }, + { "FORMATS", CFGTOK_FORMATS }, + { "FEATURES", CFGTOK_FEATURES }, }; - unsigned BlockTok; + cfgtok_t BlockTok; do { @@ -947,23 +1126,27 @@ static void ParseConfig (void) switch (BlockTok) { case CFGTOK_MEMORY: - ParseMemory (); - break; + ParseMemory (); + break; case CFGTOK_FILES: - ParseFiles (); - break; + ParseFiles (); + break; case CFGTOK_SEGMENTS: - ParseSegments (); - break; + ParseSegments (); + break; case CFGTOK_FORMATS: - ParseFormats (); + ParseFormats (); + break; + + case CFGTOK_FEATURES: + ParseFeatures (); break; default: - FAIL ("Unexpected block token"); + FAIL ("Unexpected block token"); } diff --git a/src/ld65/exports.c b/src/ld65/exports.c index ae72b280f..515b8527d 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -45,10 +45,10 @@ #include "xmalloc.h" /* ld65 */ -#include "global.h" +#include "condes.h" #include "error.h" #include "fileio.h" -#include "initfunc.h" +#include "global.h" #include "objdata.h" #include "expr.h" #include "exports.h" @@ -202,17 +202,18 @@ static Export* NewExport (unsigned char Type, const char* Name, ObjData* Obj) /* Initialize the fields */ E->Next = 0; - E->Flags = 0; + E->Flags = 0; E->Obj = Obj; E->ImpCount = 0; E->ImpList = 0; E->Expr = 0; E->Type = Type; + memset (E->ConDes, 0, sizeof (E->ConDes)); if (Name) { E->Name = xstrdup (Name); } else { - /* Name will get added later */ - E->Name = 0; + /* Name will get added later */ + E->Name = 0; } /* Return the new entry */ @@ -229,9 +230,9 @@ 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)) { - AddInitFunc (E); + /* Insert the export into any condes tables if needed */ + if (IS_EXP_CONDES (E->Type)) { + ConDesAddExport (E); } /* Create a hash value for the given name */ @@ -272,7 +273,7 @@ void InsertExport (Export* E) } } else { /* Duplicate entry, ignore it */ - Warning ("Duplicate external identifier: `%s'", L->Name); + Warning ("Duplicate external identifier: `%s'", L->Name); } return; } @@ -293,6 +294,7 @@ Export* ReadExport (FILE* F, ObjData* O) /* Read an export from a file */ { unsigned char Type; + unsigned ConDesCount; Export* E; /* Read the type */ @@ -301,6 +303,29 @@ Export* ReadExport (FILE* F, ObjData* O) /* Create a new export without a name */ E = NewExport (Type, 0, O); + /* Read the constructor/destructor decls if we have any */ + ConDesCount = GET_EXP_CONDES_COUNT (Type); + if (ConDesCount > 0) { + + unsigned char ConDes[CD_TYPE_COUNT]; + unsigned I; + + /* Read the data into temp storage */ + ReadData (F, ConDes, ConDesCount); + + /* Re-order the data. In the file, each decl is encoded into a byte + * which contains the type and the priority. In memory, we will use + * an array of types which contain the priority. This array was + * cleared by the constructor (NewExport), so we must only set the + * fields that contain values. + */ + for (I = 0; I < ConDesCount; ++I) { + unsigned ConDesType = CD_GET_TYPE (ConDes[I]); + unsigned ConDesPrio = CD_GET_PRIO (ConDes[I]); + E->ConDes[ConDesType] = ConDesPrio; + } + } + /* Read the name */ E->Name = ReadStr (F); @@ -562,7 +587,7 @@ void PrintExportMap (FILE* F) GetExportVal (E), E->ImpCount? 'R' : ' ', IS_EXP_ZP (E->Type)? 'Z' : ' ', - IS_EXP_INIT (E->Type)? 'I' : ' '); + IS_EXP_CONDES (E->Type)? 'I' : ' '); if (++Count == 2) { Count = 0; fprintf (F, "\n"); diff --git a/src/ld65/exports.h b/src/ld65/exports.h index df3567610..8ee675f0c 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -41,6 +41,7 @@ #include /* common */ +#include "cddefs.h" #include "exprdefs.h" #include "filepos.h" @@ -81,7 +82,8 @@ struct Export { Import* ImpList; /* List of imports for this symbol */ FilePos Pos; /* File position of definition */ ExprNode* Expr; /* Expression (0 if not def'd) */ - unsigned char Type; /* Type of export */ + unsigned char Type; /* Type of export */ + unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */ char* Name; /* Name - dynamically allocated */ }; @@ -157,7 +159,7 @@ void CircularRefError (const Export* E); /* Print an error about a circular reference using to define the given export */ - + /* End of exports.h */ #endif diff --git a/src/ld65/fileio.c b/src/ld65/fileio.c index c13a202f2..4998fe3ed 100644 --- a/src/ld65/fileio.c +++ b/src/ld65/fileio.c @@ -284,9 +284,12 @@ FilePos* ReadFilePos (FILE* F, FilePos* Pos) void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ -{ - if (fread (Data, 1, Size, F) != Size) { - Error ("Read error (file corrupt?)"); +{ + /* Explicitly allow reading zero bytes */ + if (Size > 0) { + if (fread (Data, 1, Size, F) != Size) { + Error ("Read error (file corrupt?)"); + } } return Data; } diff --git a/src/ld65/main.c b/src/ld65/main.c index 63ab842a4..415c39ab6 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -48,6 +48,7 @@ /* ld65 */ #include "binfmt.h" +#include "condes.h" #include "config.h" #include "error.h" #include "exports.h" @@ -404,6 +405,9 @@ int main (int argc, char* argv []) /* Read the config file */ CfgRead (); + /* Create the condes tables if requested */ + ConDesCreate (); + /* Assign start addresses for the segments, define linker symbols */ CfgAssignSegments (); @@ -424,6 +428,7 @@ int main (int argc, char* argv []) /* Dump the data for debugging */ if (Verbose > 1) { SegDump (); + ConDesDump (); } /* Return an apropriate exit code */ diff --git a/src/ld65/make/gcc.mak b/src/ld65/make/gcc.mak index abe8edf49..1b4affcc8 100644 --- a/src/ld65/make/gcc.mak +++ b/src/ld65/make/gcc.mak @@ -19,6 +19,7 @@ CVT=cfg/cvt-cfg.pl OBJS = bin.o \ binfmt.o \ + condes.o \ config.o \ dbgsyms.o \ error.o \ @@ -28,7 +29,6 @@ OBJS = bin.o \ fileio.o \ fragment.o \ global.o \ - initfunc.o \ library.o \ main.o \ mapfile.o \ diff --git a/src/ld65/scanner.c b/src/ld65/scanner.c index 56870f11e..7b0770016 100644 --- a/src/ld65/scanner.c +++ b/src/ld65/scanner.c @@ -56,7 +56,7 @@ /* Current token and attributes */ -unsigned CfgTok; +cfgtok_t CfgTok; char CfgSVal [CFG_MAX_IDENT_LEN+1]; unsigned long CfgIVal; @@ -322,7 +322,7 @@ Again: -void CfgConsume (unsigned T, const char* Msg) +void CfgConsume (cfgtok_t T, const char* Msg) /* Skip a token, print an error message if not found */ { if (CfgTok != T) { @@ -535,3 +535,4 @@ void CfgCloseInput (void) + diff --git a/src/ld65/scanner.h b/src/ld65/scanner.h index 02d534978..d5f86e3ec 100644 --- a/src/ld65/scanner.h +++ b/src/ld65/scanner.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2000 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -45,67 +45,77 @@ /* Config file tokens */ -#define CFGTOK_NONE 0 -#define CFGTOK_INTCON 1 -#define CFGTOK_STRCON 2 -#define CFGTOK_IDENT 3 -#define CFGTOK_LCURLY 4 -#define CFGTOK_RCURLY 5 -#define CFGTOK_SEMI 6 -#define CFGTOK_COMMA 7 -#define CFGTOK_EQ 8 -#define CFGTOK_COLON 9 -#define CFGTOK_DOT 10 -#define CFGTOK_EOF 11 +typedef enum { + CFGTOK_NONE, + CFGTOK_INTCON, + CFGTOK_STRCON, + CFGTOK_IDENT, + CFGTOK_LCURLY, + CFGTOK_RCURLY, + CFGTOK_SEMI, + CFGTOK_COMMA, + CFGTOK_EQ, + CFGTOK_COLON, + CFGTOK_DOT, + CFGTOK_EOF, -/* Special identifiers */ -#define CFGTOK_MEMORY 20 -#define CFGTOK_FILES 21 -#define CFGTOK_SEGMENTS 22 -#define CFGTOK_FORMATS 23 + /* Special identifiers */ + CFGTOK_MEMORY, + CFGTOK_FILES, + CFGTOK_SEGMENTS, + CFGTOK_FORMATS, + CFGTOK_FEATURES, -#define CFGTOK_START 30 -#define CFGTOK_SIZE 31 -#define CFGTOK_TYPE 32 -#define CFGTOK_FILE 33 -#define CFGTOK_DEFINE 34 -#define CFGTOK_FILL 35 -#define CFGTOK_FILLVAL 36 -#define CFGTOK_EXPORT 37 -#define CFGTOK_IMPORT 38 -#define CFGTOK_OS 39 -#define CFGTOK_FORMAT 40 + CFGTOK_START, + CFGTOK_SIZE, + CFGTOK_TYPE, + CFGTOK_FILE, + CFGTOK_DEFINE, + CFGTOK_FILL, + CFGTOK_FILLVAL, + CFGTOK_EXPORT, + CFGTOK_IMPORT, + CFGTOK_OS, + CFGTOK_FORMAT, -#define CFGTOK_LOAD 50 -#define CFGTOK_RUN 51 -#define CFGTOK_ALIGN 52 -#define CFGTOK_OFFSET 53 + CFGTOK_LOAD, + CFGTOK_RUN, + CFGTOK_ALIGN, + CFGTOK_OFFSET, -#define CFGTOK_RO 60 -#define CFGTOK_RW 61 -#define CFGTOK_BSS 62 -#define CFGTOK_ZP 63 -#define CFGTOK_WPROT 64 + CFGTOK_RO, + CFGTOK_RW, + CFGTOK_BSS, + CFGTOK_ZP, + CFGTOK_WPROT, -#define CFGTOK_O65 70 -#define CFGTOK_BIN 71 + CFGTOK_O65, + CFGTOK_BIN, -#define CFGTOK_SMALL 80 -#define CFGTOK_LARGE 81 + CFGTOK_SMALL, + CFGTOK_LARGE, -#define CFGTOK_TRUE 90 -#define CFGTOK_FALSE 91 + CFGTOK_TRUE, + CFGTOK_FALSE, -#define CFGTOK_LUNIX 100 -#define CFGTOK_OSA65 101 + CFGTOK_LUNIX, + CFGTOK_OSA65, + + CFGTOK_CONDES, + CFGTOK_SEGMENT, + CFGTOK_LABEL, + CFGTOK_CONSTRUCTOR, + CFGTOK_DESTRUCTOR + +} cfgtok_t; /* Mapping table entry, special identifier --> token */ typedef struct IdentTok_ IdentTok; struct IdentTok_ { - const char* Ident; /* Identifier */ - unsigned Tok; /* Token for identifier */ + const char* Ident; /* Identifier */ + cfgtok_t Tok; /* Token for identifier */ }; #define ENTRY_COUNT(s) (sizeof (s) / sizeof (s [0])) @@ -113,7 +123,7 @@ struct IdentTok_ { /* Current token and attributes */ #define CFG_MAX_IDENT_LEN 255 -extern unsigned CfgTok; +extern cfgtok_t CfgTok; extern char CfgSVal [CFG_MAX_IDENT_LEN+1]; extern unsigned long CfgIVal; @@ -138,7 +148,7 @@ void CfgError (const char* Format, ...) attribute((format(printf,1,2))); void CfgNextTok (void); /* Read the next token from the input stream */ -void CfgConsume (unsigned T, const char* Msg); +void CfgConsume (cfgtok_t T, const char* Msg); /* Skip a token, print an error message if not found */ void CfgConsumeSemi (void); @@ -196,4 +206,4 @@ void CfgCloseInput (void); - + diff --git a/src/od65/dump.c b/src/od65/dump.c index f5b880bda..d44e12efd 100644 --- a/src/od65/dump.c +++ b/src/od65/dump.c @@ -37,6 +37,7 @@ #include /* common */ +#include "cddefs.h" #include "exprdefs.h" #include "filepos.h" #include "objdefs.h" @@ -196,24 +197,42 @@ static unsigned SkipFragment (FILE* F) -static const char* GetExportFlags (unsigned Flags) +static const char* GetExportFlags (unsigned Flags, const unsigned char* ConDes) /* Get the export flags as a (static) string */ { /* Static buffer */ - static char TypeDesc[128]; + static char TypeDesc[256]; + static char* T; - /* Get the flags */ + unsigned Count; + unsigned I; + + /* Adressing mode */ TypeDesc[0] = '\0'; switch (Flags & EXP_MASK_SIZE) { - case EXP_ABS: strcat (TypeDesc, "EXP_ABS"); break; - case EXP_ZP: strcat (TypeDesc, "EXP_ZP"); break; + case EXP_ABS: strcat (TypeDesc, "EXP_ABS"); break; + case EXP_ZP: strcat (TypeDesc, "EXP_ZP"); break; } + + /* Type of expression */ switch (Flags & EXP_MASK_VAL) { - case EXP_CONST: strcat (TypeDesc, ",EXP_CONST"); break; - case EXP_EXPR: strcat (TypeDesc, ",EXP_EXPR"); break; + case EXP_CONST: strcat (TypeDesc, ",EXP_CONST"); break; + case EXP_EXPR: strcat (TypeDesc, ",EXP_EXPR"); break; } - if (IS_EXP_INIT (Flags)) { - sprintf (TypeDesc+strlen(TypeDesc), ",EXP_INIT=%u", GET_EXP_INIT_VAL(Flags)); + + /* Constructor/destructor declarations */ + T = TypeDesc + strlen (TypeDesc); + Count = GET_EXP_CONDES_COUNT (Flags); + if (Count > 0) { + T += sprintf (T, ",EXP_CONDES="); + for (I = 0; I < Count; ++I) { + unsigned Type = CD_GET_TYPE (ConDes[I]); + unsigned Prio = CD_GET_PRIO (ConDes[I]); + if (I > 0) { + *T++ = ','; + } + T += sprintf (T, "[%u,%u]", Type, Prio); + } } /* Return the result */ @@ -537,10 +556,10 @@ void DumpObjImports (FILE* F, unsigned long Offset) void DumpObjExports (FILE* F, unsigned long Offset) /* Dump the exports in the object file */ { - ObjHeader H; - unsigned Count; - unsigned I; - FilePos Pos; + ObjHeader H; + unsigned Count; + unsigned I; + FilePos Pos; /* Seek to the header position */ FileSeek (F, Offset); @@ -563,12 +582,18 @@ void DumpObjExports (FILE* F, unsigned long Offset) unsigned long Value = 0; int HaveValue; + unsigned char Type; + unsigned char ConDes [CD_TYPE_COUNT]; + char* Name; + unsigned Len; + /* Read the data for one export */ - unsigned char Type = Read8 (F); - char* Name = ReadStr (F); - unsigned Len = strlen (Name); - if (Type & EXP_EXPR) { + Type = Read8 (F); + ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type)); + Name = ReadStr (F); + Len = strlen (Name); + if (IS_EXP_EXPR (Type)) { SkipExpr (F); HaveValue = 0; } else { @@ -581,7 +606,7 @@ void DumpObjExports (FILE* F, unsigned long Offset) printf (" Index:%27u\n", I); /* Print the data */ - printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type)); + printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes)); printf (" Name:%*s\"%s\"\n", 24-Len, "", Name); if (HaveValue) { printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value); @@ -630,12 +655,17 @@ void DumpObjDbgSyms (FILE* F, unsigned long Offset) unsigned long Value = 0; int HaveValue; + unsigned char Type; + unsigned char ConDes [CD_TYPE_COUNT]; + char* Name; + unsigned Len; /* Read the data for one symbol */ - unsigned char Type = Read8 (F); - char* Name = ReadStr (F); - unsigned Len = strlen (Name); - if (Type & EXP_EXPR) { + Type = Read8 (F); + ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type)); + Name = ReadStr (F); + Len = strlen (Name); + if (IS_EXP_EXPR (Type)) { SkipExpr (F); HaveValue = 0; } else { @@ -648,7 +678,7 @@ void DumpObjDbgSyms (FILE* F, unsigned long Offset) printf (" Index:%27u\n", I); /* Print the data */ - printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type)); + printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes)); printf (" Name:%*s\"%s\"\n", 24-Len, "", Name); if (HaveValue) { printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value); diff --git a/src/od65/fileio.c b/src/od65/fileio.c index f700f3186..1950400e0 100644 --- a/src/od65/fileio.c +++ b/src/od65/fileio.c @@ -179,8 +179,11 @@ FilePos* ReadFilePos (FILE* F, FilePos* Pos) void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ { - if (fread (Data, 1, Size, F) != Size) { - Error ("Read error (file corrupt?)"); + /* Accept zero sized reads */ + if (Size > 0) { + if (fread (Data, 1, Size, F) != Size) { + Error ("Read error (file corrupt?)"); + } } return Data; }