mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
Working on the condes feature
git-svn-id: svn://svn.cc65.org/cc65/trunk@451 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
9c35f5278a
commit
b9970cb7da
@ -286,6 +286,3 @@ void ObjExtract (const char* Name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* ca65 */
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "exprdefs.h"
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "hashstr.h"
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "optdefs.h"
|
||||
#include "xmalloc.h"
|
||||
|
@ -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 */
|
||||
/*****************************************************************************/
|
||||
@ -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 },
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
@ -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 },
|
||||
|
@ -121,7 +121,9 @@ enum Token {
|
||||
TOK_CASE,
|
||||
TOK_CODE,
|
||||
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,
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <string.h>
|
||||
|
||||
/* 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,7 +97,8 @@ 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 */
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -34,10 +34,13 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
#include "../common/xsprintf.h"
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
#include "xsprintf.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "error.h"
|
||||
#include "asmline.h"
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* cc65 */
|
||||
#include "error.h"
|
||||
#include "scanner.h"
|
||||
|
@ -34,8 +34,10 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* cc65 */
|
||||
#include "codegen.h"
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
|
@ -33,8 +33,12 @@
|
||||
|
||||
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "symentry.h"
|
||||
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* initfunc.c */
|
||||
/* cddefs.h */
|
||||
/* */
|
||||
/* Init/cleanup function handling */
|
||||
/* Definitions for module constructor/destructors */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
@ -33,13 +33,8 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
|
||||
/* ld65 */
|
||||
#include "exports.h"
|
||||
#include "segments.h"
|
||||
#include "initfunc.h"
|
||||
#ifndef CDDEFS_H
|
||||
#define CDDEFS_H
|
||||
|
||||
|
||||
|
||||
@ -49,31 +44,37 @@
|
||||
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)++)
|
||||
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "target.h"
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if defined(_MSC_VER)
|
||||
/* Microsoft compiler */
|
||||
# include <io.h>
|
||||
|
188
src/ld65/condes.c
Normal file
188
src/ld65/condes.c
Normal file
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* initfunc.h */
|
||||
/* condes.h */
|
||||
/* */
|
||||
/* Init/cleanup function handling */
|
||||
/* Module constructor/destructor support */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
@ -33,8 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#ifndef INITFUNC_H
|
||||
#define INITFUNC_H
|
||||
#ifndef CONDES_H
|
||||
#define CONDES_H
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
@ -44,12 +44,13 @@
|
||||
#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) {
|
||||
Memory* M = CfgFindMemory (Name);
|
||||
if (M) {
|
||||
CfgError ("Memory area `%s' defined twice", Name);
|
||||
break;
|
||||
}
|
||||
M = M->Next;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
SegDesc* S = CfgFindSegDesc (Name);
|
||||
if (S) {
|
||||
CfgError ("Segment `%s' defined twice", Name);
|
||||
break;
|
||||
}
|
||||
S = S->Next;
|
||||
}
|
||||
|
||||
/* 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,6 +952,154 @@ 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 */
|
||||
{
|
||||
@ -930,8 +1108,9 @@ static void ParseConfig (void)
|
||||
{ "FILES", CFGTOK_FILES },
|
||||
{ "SEGMENTS", CFGTOK_SEGMENTS },
|
||||
{ "FORMATS", CFGTOK_FORMATS },
|
||||
{ "FEATURES", CFGTOK_FEATURES },
|
||||
};
|
||||
unsigned BlockTok;
|
||||
cfgtok_t BlockTok;
|
||||
|
||||
do {
|
||||
|
||||
@ -962,6 +1141,10 @@ static void ParseConfig (void)
|
||||
ParseFormats ();
|
||||
break;
|
||||
|
||||
case CFGTOK_FEATURES:
|
||||
ParseFeatures ();
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ("Unexpected block token");
|
||||
|
||||
|
@ -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"
|
||||
@ -208,6 +208,7 @@ static Export* NewExport (unsigned char Type, const char* Name, ObjData* Obj)
|
||||
E->ImpList = 0;
|
||||
E->Expr = 0;
|
||||
E->Type = Type;
|
||||
memset (E->ConDes, 0, sizeof (E->ConDes));
|
||||
if (Name) {
|
||||
E->Name = xstrdup (Name);
|
||||
} else {
|
||||
@ -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 */
|
||||
@ -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");
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* common */
|
||||
#include "cddefs.h"
|
||||
#include "exprdefs.h"
|
||||
#include "filepos.h"
|
||||
|
||||
@ -82,6 +83,7 @@ struct Export {
|
||||
FilePos Pos; /* File position of definition */
|
||||
ExprNode* Expr; /* Expression (0 if not def'd) */
|
||||
unsigned char Type; /* Type of export */
|
||||
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
|
||||
char* Name; /* Name - dynamically allocated */
|
||||
};
|
||||
|
||||
|
@ -285,9 +285,12 @@ FilePos* ReadFilePos (FILE* F, FilePos* Pos)
|
||||
void* ReadData (FILE* F, void* Data, unsigned Size)
|
||||
/* Read data from the file */
|
||||
{
|
||||
/* Explicitly allow reading zero bytes */
|
||||
if (Size > 0) {
|
||||
if (fread (Data, 1, Size, F) != Size) {
|
||||
Error ("Read error (file corrupt?)");
|
||||
}
|
||||
}
|
||||
return Data;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 \
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
@ -45,59 +45,69 @@
|
||||
|
||||
|
||||
/* 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
|
||||
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;
|
||||
|
||||
|
||||
|
||||
@ -105,7 +115,7 @@
|
||||
typedef struct IdentTok_ IdentTok;
|
||||
struct IdentTok_ {
|
||||
const char* Ident; /* Identifier */
|
||||
unsigned Tok; /* Token for 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);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <time.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Type of expression */
|
||||
switch (Flags & EXP_MASK_VAL) {
|
||||
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 */
|
||||
@ -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);
|
||||
|
@ -179,9 +179,12 @@ FilePos* ReadFilePos (FILE* F, FilePos* Pos)
|
||||
void* ReadData (FILE* F, void* Data, unsigned Size)
|
||||
/* Read data from the file */
|
||||
{
|
||||
/* Accept zero sized reads */
|
||||
if (Size > 0) {
|
||||
if (fread (Data, 1, Size, F) != Size) {
|
||||
Error ("Read error (file corrupt?)");
|
||||
}
|
||||
}
|
||||
return Data;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user