+#include <string.h>
+
/* ca65 */
#include "error.h"
#include "expr.h"
+#include <string.h>
+
/* common */
#include "check.h"
#include "exprdefs.h"
+#include <string.h>
+
/* common */
#include "check.h"
#include "hashstr.h"
#include <stdio.h>
+#include <string.h>
/* common */
#include "check.h"
-
+
/* ca65 */
#include "error.h"
#include "expr.h"
+#include <string.h>
+
/* common */
#include "optdefs.h"
#include "xmalloc.h"
/* common */
#include "bitops.h"
+#include "cddefs.h"
#include "check.h"
#include "symdefs.h"
#include "tgttrans.h"
+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 */
/*****************************************************************************/
NextTok ();
/* Do smart handling of dangling comma */
if (Tok == TOK_SEP) {
- Error (ERR_UNEXPECTED_EOL);
+ Error (ERR_UNEXPECTED_EOL);
break;
}
}
+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 */
{
+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 */
{
-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
{ ccNone, DoCase },
{ ccNone, DoCode },
{ ccNone, DoUnexpected, }, /* .CONCAT */
+ { ccNone, DoConDes },
{ ccNone, DoUnexpected }, /* .CONST */
+ { ccNone, DoConstructor },
{ ccNone, DoUnexpected }, /* .CPU */
{ ccNone, DoData },
{ ccNone, DoDbg, },
{ ccNone, DoDebugInfo },
{ ccNone, DoDefine },
{ ccNone, DoUnexpected }, /* .DEFINED */
+ { ccNone, DoDestructor },
{ ccNone, DoDWord },
{ ccKeepToken, DoConditionals }, /* .ELSE */
{ ccKeepToken, DoConditionals }, /* .ELSEIF */
{ ccNone, DoImportZP },
{ ccNone, DoIncBin },
{ ccNone, DoInclude },
- { ccNone, DoInitializer },
{ ccNone, DoInvalid }, /* .LEFT */
{ ccNone, DoLineCont },
{ ccNone, DoList },
+#include <string.h>
+
/* common */
#include "xmalloc.h"
/* 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;
{ "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 },
{ "DEF", TOK_DEFINED },
{ "DEFINE", TOK_DEFINE },
{ "DEFINED", TOK_DEFINED },
+ { "DESTRUCTOR", TOK_DESTRUCTOR },
{ "DWORD", TOK_DWORD },
{ "ELSE", TOK_ELSE },
{ "ELSEIF", TOK_ELSEIF },
{ "IMPORTZP", TOK_IMPORTZP },
{ "INCBIN", TOK_INCBIN },
{ "INCLUDE", TOK_INCLUDE },
- { "INITIALIZER", TOK_INITIALIZER },
{ "LEFT", TOK_LEFT },
{ "LINECONT", TOK_LINECONT },
{ "LIST", TOK_LIST },
TOK_BYTE,
TOK_CASE,
TOK_CODE,
- TOK_CONCAT,
+ TOK_CONCAT,
+ TOK_CONDES,
TOK_CONST,
+ TOK_CONSTRUCTOR,
TOK_CPU,
TOK_DATA,
TOK_DBG,
TOK_DEBUGINFO,
TOK_DEFINE,
TOK_DEFINED,
+ TOK_DESTRUCTOR,
TOK_DWORD,
TOK_ELSE,
TOK_ELSEIF,
TOK_IMPORTZP,
TOK_INCBIN,
TOK_INCLUDE,
- TOK_INITIALIZER,
TOK_LEFT,
TOK_LINECONT,
TOK_LIST,
#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_INDEXED 0x0800 /* Index is valid */
#define SF_CONST 0x1000 /* The symbol has a constant value */
#define SF_MULTDEF 0x2000 /* Multiply defined symbol */
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 */
static int IsLocal (const char* Name)
/* Return true if Name is the name of a local symbol */
-{
+{
return (*Name == LocalStart);
}
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 */
-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)) {
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;
}
/* 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 ();
/* 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);
/* 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);
* 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);
#include <stdio.h>
-
-#include "../common/xmalloc.h"
-#include "../common/xsprintf.h"
-
+#include <string.h>
+
+/* common */
+#include "xmalloc.h"
+#include "xsprintf.h"
+
+/* cc65 */
#include "error.h"
#include "asmline.h"
+#include <string.h>
+
/* cc65 */
#include "error.h"
#include "scanner.h"
/* Parse an additional __attribute__ modifier */
{
ident AttrName;
- attrib_t AttrType;
+ attrib_t AttrType;
/* Initialize the attribute description with "no attribute" */
A->AttrType = atNone;
#include <stdlib.h>
+#include <string.h>
#include <ctype.h>
-
+
+/* cc65 */
#include "codegen.h"
#include "error.h"
#include "expr.h"
-#include "../common/xmalloc.h"
-
+#include <string.h>
+
+/* common */
+#include "xmalloc.h"
+
+/* cc65 */
#include "symentry.h"
/* Code */
/*****************************************************************************/
-
+
SymEntry* NewSymEntry (const char* Name, unsigned Flags)
/* Create a new symbol table with the given name */
--- /dev/null
+/*****************************************************************************/
+/* */
+/* cddefs.h */
+/* */
+/* Definitions for module constructor/destructors */
+/* */
+/* */
+/* */
+/* (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 CDDEFS_H
+#define CDDEFS_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* 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))
+
+
+
+/* End of cddefs.h */
+
+#endif
+
+
+
-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. */
+{
+ /* 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.
*/
{
- /* Use qsort */
- qsort (C->Items, C->Count, sizeof (void*), Compare);
+ if (C->Count > 1) {
+ QuickSort (C, 0, C->Count-1, Compare, Data);
+ }
}
* 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.
*/
/* 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
/* 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)++)
#include <stdlib.h>
+#include <string.h>
#include <ctype.h>
#include "target.h"
#include <stdio.h>
+#include <string.h>
#if defined(_MSC_VER)
/* Microsoft compiler */
# include <io.h>
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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));
+ }
+}
+
+
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef CONDES_H
+#define CONDES_H
+
+
+
+/*****************************************************************************/
+/* Forwards */
+/*****************************************************************************/
+
+
+
+struct Export;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void ConDesAddExport (struct Export* E);
+/* Add the given export to the list of constructors/destructor */
+
+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 condes.h */
+
+#endif
+
+
+
+
#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"
+/*****************************************************************************/
+/* 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 */
/*****************************************************************************/
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 */
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 */
-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 */
{
while (CfgTok == CFGTOK_IDENT) {
/* Map the identifier to a token */
- unsigned AttrTok;
+ cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
AttrTok = CfgTok;
while (CfgTok == CFGTOK_IDENT) {
/* Map the identifier to a token */
- unsigned AttrTok;
+ cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
AttrTok = CfgTok;
-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 */
{
while (CfgTok == CFGTOK_IDENT) {
/* Map the identifier to a token */
- unsigned AttrTok;
+ cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
AttrTok = CfgTok;
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;
while (CfgTok == CFGTOK_IDENT) {
/* Map the identifier to a token */
- unsigned AttrTok;
+ cfgtok_t AttrTok;
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
AttrTok = CfgTok;
break;
default:
- Error ("Unexpected type token");
+ CfgError ("Unexpected type token");
}
break;
break;
default:
- Error ("Unexpected OS token");
+ CfgError ("Unexpected OS token");
}
break;
while (CfgTok == CFGTOK_IDENT) {
/* Map the identifier to a token */
- unsigned FormatTok;
+ cfgtok_t FormatTok;
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
FormatTok = CfgTok;
+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 {
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");
}
#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"
/* 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 */
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 */
}
} else {
/* Duplicate entry, ignore it */
- Warning ("Duplicate external identifier: `%s'", L->Name);
+ Warning ("Duplicate external identifier: `%s'", L->Name);
}
return;
}
/* Read an export from a file */
{
unsigned char Type;
+ unsigned ConDesCount;
Export* E;
/* Read the type */
/* 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);
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");
#include <stdio.h>
/* common */
+#include "cddefs.h"
#include "exprdefs.h"
#include "filepos.h"
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 */
};
/* Print an error about a circular reference using to define the given export */
-
+
/* End of exports.h */
#endif
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;
}
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* initfunc.c */
-/* */
-/* Init/cleanup function handling */
-/* */
-/* */
-/* */
-/* (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 "coll.h"
-
-/* ld65 */
-#include "exports.h"
-#include "segments.h"
-#include "initfunc.h"
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-/* List of all exports that are also initializers/cleanup functions */
-static Collection InitFunctions = STATIC_COLLECTION_INITIALIZER;
-static Collection CleanupFunctions = STATIC_COLLECTION_INITIALIZER;
-
-
-
-/*****************************************************************************/
-/* 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);
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* initfunc.h */
-/* */
-/* Init/cleanup function handling */
-/* */
-/* */
-/* */
-/* (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 INITFUNC_H
-#define INITFUNC_H
-
-
-
-/*****************************************************************************/
-/* Forwards */
-/*****************************************************************************/
-
-
-
-struct Export;
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-void AddInitFunc (struct Export* E);
-/* Add the given export to the list of initializers */
-
-void AddCleanupFunc (struct Export* E);
-/* Add the given export to the list of cleanup functions */
-
-
-
-/* End of initfunc.h */
-
-#endif
-
-
-
-
/* ld65 */
#include "binfmt.h"
+#include "condes.h"
#include "config.h"
#include "error.h"
#include "exports.h"
/* Read the config file */
CfgRead ();
+ /* Create the condes tables if requested */
+ ConDesCreate ();
+
/* Assign start addresses for the segments, define linker symbols */
CfgAssignSegments ();
/* Dump the data for debugging */
if (Verbose > 1) {
SegDump ();
+ ConDesDump ();
}
/* Return an apropriate exit code */
OBJS = bin.o \
binfmt.o \
+ condes.o \
config.o \
dbgsyms.o \
error.o \
fileio.o \
fragment.o \
global.o \
- initfunc.o \
library.o \
main.o \
mapfile.o \
/* Current token and attributes */
-unsigned CfgTok;
+cfgtok_t CfgTok;
char CfgSVal [CFG_MAX_IDENT_LEN+1];
unsigned long CfgIVal;
-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) {
+
/* */
/* */
/* */
-/* (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 */
/* 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
-
-/* Special identifiers */
-#define CFGTOK_MEMORY 20
-#define CFGTOK_FILES 21
-#define CFGTOK_SEGMENTS 22
-#define CFGTOK_FORMATS 23
-
-#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
-
-#define CFGTOK_LOAD 50
-#define CFGTOK_RUN 51
-#define CFGTOK_ALIGN 52
-#define CFGTOK_OFFSET 53
-
-#define CFGTOK_RO 60
-#define CFGTOK_RW 61
-#define CFGTOK_BSS 62
-#define CFGTOK_ZP 63
-#define CFGTOK_WPROT 64
-
-#define CFGTOK_O65 70
-#define CFGTOK_BIN 71
-
-#define CFGTOK_SMALL 80
-#define CFGTOK_LARGE 81
-
-#define CFGTOK_TRUE 90
-#define CFGTOK_FALSE 91
-
-#define CFGTOK_LUNIX 100
-#define CFGTOK_OSA65 101
+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 */
+ CFGTOK_MEMORY,
+ CFGTOK_FILES,
+ CFGTOK_SEGMENTS,
+ CFGTOK_FORMATS,
+ CFGTOK_FEATURES,
+
+ CFGTOK_START,
+ CFGTOK_SIZE,
+ CFGTOK_TYPE,
+ CFGTOK_FILE,
+ CFGTOK_DEFINE,
+ CFGTOK_FILL,
+ CFGTOK_FILLVAL,
+ CFGTOK_EXPORT,
+ CFGTOK_IMPORT,
+ CFGTOK_OS,
+ CFGTOK_FORMAT,
+
+ CFGTOK_LOAD,
+ CFGTOK_RUN,
+ CFGTOK_ALIGN,
+ CFGTOK_OFFSET,
+
+ CFGTOK_RO,
+ CFGTOK_RW,
+ CFGTOK_BSS,
+ CFGTOK_ZP,
+ CFGTOK_WPROT,
+
+ CFGTOK_O65,
+ CFGTOK_BIN,
+
+ CFGTOK_SMALL,
+ CFGTOK_LARGE,
+
+ CFGTOK_TRUE,
+ CFGTOK_FALSE,
+
+ 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]))
/* 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;
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);
-
+
#include <time.h>
/* common */
+#include "cddefs.h"
#include "exprdefs.h"
#include "filepos.h"
#include "objdefs.h"
-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 */
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);
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 {
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);
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 {
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);
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;
}