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:
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,13 +33,13 @@
|
||||
|
||||
|
||||
|
||||
#ifndef INITFUNC_H
|
||||
#define INITFUNC_H
|
||||
#ifndef CONDES_H
|
||||
#define CONDES_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@@ -54,15 +54,36 @@ struct Export;
|
||||
|
||||
|
||||
|
||||
void AddInitFunc (struct Export* E);
|
||||
/* Add the given export to the list of initializers */
|
||||
void ConDesAddExport (struct Export* E);
|
||||
/* Add the given export to the list of constructors/destructor */
|
||||
|
||||
void AddCleanupFunc (struct Export* E);
|
||||
/* Add the given export to the list of cleanup functions */
|
||||
void ConDesSetSegName (unsigned Type, const char* SegName);
|
||||
/* Set the segment name where the table should go */
|
||||
|
||||
void ConDesSetLabel (unsigned Type, const char* Name);
|
||||
/* Set the label for the given ConDes type */
|
||||
|
||||
const char* ConDesGetSegName (unsigned Type);
|
||||
/* Return the segment name for the given ConDes type */
|
||||
|
||||
const char* ConDesGetLabel (unsigned Type);
|
||||
/* Return the label for the given ConDes type */
|
||||
|
||||
int ConDesHasSegName (unsigned Type);
|
||||
/* Return true if a segment name is already defined for this ConDes type */
|
||||
|
||||
int ConDesHasLabel (unsigned Type);
|
||||
/* Return true if a label is already defined for this ConDes type */
|
||||
|
||||
void ConDesCreate (void);
|
||||
/* Create the condes tables if requested */
|
||||
|
||||
void ConDesDump (void);
|
||||
/* Dump ConDes data to stdout for debugging */
|
||||
|
||||
|
||||
|
||||
/* End of initfunc.h */
|
||||
/* End of condes.h */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,14 +42,15 @@
|
||||
#include "check.h"
|
||||
#include "bitops.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
||||
/* ld65 */
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "bin.h"
|
||||
#include "o65.h"
|
||||
#include "binfmt.h"
|
||||
#include "condes.h"
|
||||
#include "error.h"
|
||||
#include "exports.h"
|
||||
#include "global.h"
|
||||
#include "o65.h"
|
||||
#include "scanner.h"
|
||||
#include "config.h"
|
||||
|
||||
@@ -115,6 +116,141 @@ static unsigned O65Attr = 0;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static File* NewFile (const char* Name);
|
||||
/* Create a new file descriptor and insert it into the list */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* List management */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static File* FindFile (const char* Name)
|
||||
/* Find a file with a given name. */
|
||||
{
|
||||
File* F = FileList;
|
||||
while (F) {
|
||||
if (strcmp (F->Name, Name) == 0) {
|
||||
return F;
|
||||
}
|
||||
F = F->Next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static File* GetFile (const char* Name)
|
||||
/* Get a file entry with the given name. Create a new one if needed. */
|
||||
{
|
||||
File* F = FindFile (Name);
|
||||
if (F == 0) {
|
||||
/* Create a new one */
|
||||
F = NewFile (Name);
|
||||
}
|
||||
return F;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void FileInsert (File* F, Memory* M)
|
||||
/* Insert the memory area into the files list */
|
||||
{
|
||||
M->F = F;
|
||||
if (F->MemList == 0) {
|
||||
/* First entry */
|
||||
F->MemList = M;
|
||||
} else {
|
||||
F->MemLast->FNext = M;
|
||||
}
|
||||
F->MemLast = M;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Memory* CfgFindMemory (const char* Name)
|
||||
/* Find the memory are with the given name. Return NULL if not found */
|
||||
{
|
||||
Memory* M = MemoryList;
|
||||
while (M) {
|
||||
if (strcmp (M->Name, Name) == 0) {
|
||||
return M;
|
||||
}
|
||||
M = M->Next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Memory* CfgGetMemory (const char* Name)
|
||||
/* Find the memory are with the given name. Print an error on an invalid name */
|
||||
{
|
||||
Memory* M = CfgFindMemory (Name);
|
||||
if (M == 0) {
|
||||
CfgError ("Invalid memory area `%s'", Name);
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SegDesc* CfgFindSegDesc (const char* Name)
|
||||
/* Find the segment descriptor with the given name, return NULL if not found. */
|
||||
{
|
||||
SegDesc* S = SegDescList;
|
||||
while (S) {
|
||||
if (strcmp (S->Name, Name) == 0) {
|
||||
/* Found */
|
||||
return S;
|
||||
}
|
||||
S = S->Next;
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void SegDescInsert (SegDesc* S)
|
||||
/* Insert a segment descriptor into the list of segment descriptors */
|
||||
{
|
||||
/* Insert the struct into the list */
|
||||
S->Next = SegDescList;
|
||||
SegDescList = S;
|
||||
++SegDescCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void MemoryInsert (Memory* M, SegDesc* S)
|
||||
/* Insert the segment descriptor into the memory area list */
|
||||
{
|
||||
/* Create a new node for the entry */
|
||||
MemListNode* N = xmalloc (sizeof (MemListNode));
|
||||
N->Seg = S;
|
||||
N->Next = 0;
|
||||
|
||||
if (M->SegLast == 0) {
|
||||
/* First entry */
|
||||
M->SegList = N;
|
||||
} else {
|
||||
M->SegLast->Next = N;
|
||||
}
|
||||
M->SegLast = N;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Constructors/Destructors */
|
||||
/*****************************************************************************/
|
||||
@@ -156,13 +292,9 @@ static Memory* NewMemory (const char* Name)
|
||||
unsigned Len = strlen (Name);
|
||||
|
||||
/* Check for duplicate names */
|
||||
Memory* M = MemoryList;
|
||||
while (M) {
|
||||
if (strcmp (M->Name, Name) == 0) {
|
||||
CfgError ("Memory area `%s' defined twice", Name);
|
||||
break;
|
||||
}
|
||||
M = M->Next;
|
||||
Memory* M = CfgFindMemory (Name);
|
||||
if (M) {
|
||||
CfgError ("Memory area `%s' defined twice", Name);
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
@@ -208,13 +340,9 @@ static SegDesc* NewSegDesc (const char* Name)
|
||||
unsigned Len = strlen (Name);
|
||||
|
||||
/* Check for duplicate names */
|
||||
SegDesc* S = SegDescList;
|
||||
while (S) {
|
||||
if (strcmp (S->Name, Name) == 0) {
|
||||
CfgError ("Segment `%s' defined twice", Name);
|
||||
break;
|
||||
}
|
||||
S = S->Next;
|
||||
SegDesc* S = CfgFindSegDesc (Name);
|
||||
if (S) {
|
||||
CfgError ("Segment `%s' defined twice", Name);
|
||||
}
|
||||
|
||||
/* Verify that the given segment does really exist */
|
||||
@@ -278,49 +406,6 @@ static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
|
||||
|
||||
|
||||
|
||||
static File* FindFile (const char* Name)
|
||||
/* Find a file with a given name. */
|
||||
{
|
||||
File* F = FileList;
|
||||
while (F) {
|
||||
if (strcmp (F->Name, Name) == 0) {
|
||||
return F;
|
||||
}
|
||||
F = F->Next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static File* GetFile (const char* Name)
|
||||
/* Get a file entry with the given name. Create a new one if needed. */
|
||||
{
|
||||
File* F = FindFile (Name);
|
||||
if (F == 0) {
|
||||
/* Create a new one */
|
||||
F = NewFile (Name);
|
||||
}
|
||||
return F;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void FileInsert (File* F, Memory* M)
|
||||
/* Insert the memory area into the files list */
|
||||
{
|
||||
M->F = F;
|
||||
if (F->MemList == 0) {
|
||||
/* First entry */
|
||||
F->MemList = M;
|
||||
} else {
|
||||
F->MemLast->FNext = M;
|
||||
}
|
||||
F->MemLast = M;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseMemory (void)
|
||||
/* Parse a MEMORY section */
|
||||
{
|
||||
@@ -351,7 +436,7 @@ static void ParseMemory (void)
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
unsigned AttrTok;
|
||||
cfgtok_t AttrTok;
|
||||
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
|
||||
AttrTok = CfgTok;
|
||||
|
||||
@@ -477,7 +562,7 @@ static void ParseFiles (void)
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
unsigned AttrTok;
|
||||
cfgtok_t AttrTok;
|
||||
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
|
||||
AttrTok = CfgTok;
|
||||
|
||||
@@ -528,63 +613,6 @@ static void ParseFiles (void)
|
||||
|
||||
|
||||
|
||||
static Memory* CfgFindMemory (const char* Name)
|
||||
/* Find the memory are with the given name. Return NULL if not found */
|
||||
{
|
||||
Memory* M = MemoryList;
|
||||
while (M) {
|
||||
if (strcmp (M->Name, Name) == 0) {
|
||||
return M;
|
||||
}
|
||||
M = M->Next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Memory* CfgGetMemory (const char* Name)
|
||||
/* Find the memory are with the given name. Print an error on an invalid name */
|
||||
{
|
||||
Memory* M = CfgFindMemory (Name);
|
||||
if (M == 0) {
|
||||
CfgError ("Invalid memory area `%s'", Name);
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void SegDescInsert (SegDesc* S)
|
||||
/* Insert a segment descriptor into the list of segment descriptors */
|
||||
{
|
||||
/* Insert the struct into the list */
|
||||
S->Next = SegDescList;
|
||||
SegDescList = S;
|
||||
++SegDescCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void MemoryInsert (Memory* M, SegDesc* S)
|
||||
/* Insert the segment descriptor into the memory area list */
|
||||
{
|
||||
/* Create a new node for the entry */
|
||||
MemListNode* N = xmalloc (sizeof (MemListNode));
|
||||
N->Seg = S;
|
||||
N->Next = 0;
|
||||
|
||||
if (M->SegLast == 0) {
|
||||
/* First entry */
|
||||
M->SegList = N;
|
||||
} else {
|
||||
M->SegLast->Next = N;
|
||||
}
|
||||
M->SegLast = N;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseSegments (void)
|
||||
/* Parse a SEGMENTS section */
|
||||
{
|
||||
@@ -623,7 +651,7 @@ static void ParseSegments (void)
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
unsigned AttrTok;
|
||||
cfgtok_t AttrTok;
|
||||
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
|
||||
AttrTok = CfgTok;
|
||||
|
||||
@@ -649,9 +677,11 @@ static void ParseSegments (void)
|
||||
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
|
||||
switch (CfgTok) {
|
||||
case CFGTOK_RO: S->Flags |= SF_RO; break;
|
||||
case CFGTOK_RW: /* Default */ break;
|
||||
case CFGTOK_BSS: S->Flags |= SF_BSS; break;
|
||||
case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break;
|
||||
case CFGTOK_WPROT: S->Flags |= (SF_RO | SF_WPROT); break;
|
||||
default: Internal ("Unexpected token: %d", CfgTok);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -788,7 +818,7 @@ static void ParseO65 (void)
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
unsigned AttrTok;
|
||||
cfgtok_t AttrTok;
|
||||
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
|
||||
AttrTok = CfgTok;
|
||||
|
||||
@@ -843,7 +873,7 @@ static void ParseO65 (void)
|
||||
break;
|
||||
|
||||
default:
|
||||
Error ("Unexpected type token");
|
||||
CfgError ("Unexpected type token");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -863,7 +893,7 @@ static void ParseO65 (void)
|
||||
break;
|
||||
|
||||
default:
|
||||
Error ("Unexpected OS token");
|
||||
CfgError ("Unexpected OS token");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -892,7 +922,7 @@ static void ParseFormats (void)
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
unsigned FormatTok;
|
||||
cfgtok_t FormatTok;
|
||||
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
|
||||
FormatTok = CfgTok;
|
||||
|
||||
@@ -922,16 +952,165 @@ static void ParseFormats (void)
|
||||
|
||||
|
||||
|
||||
static void ParseConDes (void)
|
||||
/* Parse the CONDES feature */
|
||||
{
|
||||
static const IdentTok Attributes [] = {
|
||||
{ "SEGMENT", CFGTOK_SEGMENT },
|
||||
{ "LABEL", CFGTOK_LABEL },
|
||||
{ "TYPE", CFGTOK_TYPE },
|
||||
};
|
||||
|
||||
static const IdentTok Types [] = {
|
||||
{ "CONSTRUCTOR", CFGTOK_CONSTRUCTOR },
|
||||
{ "DESTRUCTOR", CFGTOK_DESTRUCTOR },
|
||||
};
|
||||
|
||||
/* Attribute values. */
|
||||
char SegName[sizeof (CfgSVal)];
|
||||
char Label[sizeof (CfgSVal)];
|
||||
int Type = -1; /* Initialize to avoid gcc warnings */
|
||||
|
||||
/* Bitmask to remember the attributes we got already */
|
||||
enum {
|
||||
atNone = 0x0000,
|
||||
atSegName = 0x0001,
|
||||
atLabel = 0x0002,
|
||||
atType = 0x0004
|
||||
};
|
||||
unsigned AttrFlags = atNone;
|
||||
|
||||
/* Parse the attributes */
|
||||
while (1) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
cfgtok_t AttrTok;
|
||||
CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
|
||||
AttrTok = CfgTok;
|
||||
|
||||
/* An optional assignment follows */
|
||||
CfgNextTok ();
|
||||
CfgOptionalAssign ();
|
||||
|
||||
/* Check which attribute was given */
|
||||
switch (AttrTok) {
|
||||
|
||||
case CFGTOK_SEGMENT:
|
||||
/* Don't allow this twice */
|
||||
FlagAttr (&AttrFlags, atSegName, "SEGMENT");
|
||||
/* We expect an identifier */
|
||||
CfgAssureIdent ();
|
||||
/* Remember the value for later */
|
||||
strcpy (SegName, CfgSVal);
|
||||
break;
|
||||
|
||||
case CFGTOK_LABEL:
|
||||
/* Don't allow this twice */
|
||||
FlagAttr (&AttrFlags, atLabel, "LABEL");
|
||||
/* We expect an identifier */
|
||||
CfgAssureIdent ();
|
||||
/* Remember the value for later */
|
||||
strcpy (Label, CfgSVal);
|
||||
break;
|
||||
|
||||
|
||||
case CFGTOK_TYPE:
|
||||
/* Don't allow this twice */
|
||||
FlagAttr (&AttrFlags, atType, "TYPE");
|
||||
/* The type may be given as id or numerical */
|
||||
if (CfgTok == CFGTOK_INTCON) {
|
||||
CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
|
||||
Type = (int) CfgIVal;
|
||||
} else {
|
||||
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
|
||||
switch (CfgTok) {
|
||||
case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
|
||||
case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
|
||||
default: FAIL ("Unexpected type token");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ("Unexpected attribute token");
|
||||
|
||||
}
|
||||
|
||||
/* Skip the attribute value */
|
||||
CfgNextTok ();
|
||||
|
||||
/* Semicolon ends the ConDes decl, otherwise accept an optional comma */
|
||||
if (CfgTok == CFGTOK_SEMI) {
|
||||
break;
|
||||
} else if (CfgTok == CFGTOK_COMMA) {
|
||||
CfgNextTok ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have all mandatory attributes */
|
||||
AttrCheck (AttrFlags, atSegName, "SEGMENT");
|
||||
AttrCheck (AttrFlags, atLabel, "LABEL");
|
||||
AttrCheck (AttrFlags, atType, "TYPE");
|
||||
|
||||
/* Check if the condes has already attributes defined */
|
||||
if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) {
|
||||
CfgError ("CONDES attributes for type %d are already defined", Type);
|
||||
}
|
||||
|
||||
/* Define the attributes */
|
||||
ConDesSetSegName (Type, SegName);
|
||||
ConDesSetLabel (Type, Label);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseFeatures (void)
|
||||
/* Parse a features section */
|
||||
{
|
||||
static const IdentTok Features [] = {
|
||||
{ "CONDES", CFGTOK_CONDES },
|
||||
};
|
||||
|
||||
while (CfgTok == CFGTOK_IDENT) {
|
||||
|
||||
/* Map the identifier to a token */
|
||||
cfgtok_t FeatureTok;
|
||||
CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature");
|
||||
FeatureTok = CfgTok;
|
||||
|
||||
/* Skip the name and the following colon */
|
||||
CfgNextTok ();
|
||||
CfgConsumeColon ();
|
||||
|
||||
/* Parse the format options */
|
||||
switch (FeatureTok) {
|
||||
|
||||
case CFGTOK_CONDES:
|
||||
ParseConDes ();
|
||||
break;
|
||||
|
||||
default:
|
||||
Error ("Unexpected feature token");
|
||||
}
|
||||
|
||||
/* Skip the semicolon */
|
||||
CfgConsumeSemi ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseConfig (void)
|
||||
/* Parse the config file */
|
||||
{
|
||||
static const IdentTok BlockNames [] = {
|
||||
{ "MEMORY", CFGTOK_MEMORY },
|
||||
{ "FILES", CFGTOK_FILES },
|
||||
{ "SEGMENTS", CFGTOK_SEGMENTS },
|
||||
{ "FORMATS", CFGTOK_FORMATS },
|
||||
{ "MEMORY", CFGTOK_MEMORY },
|
||||
{ "FILES", CFGTOK_FILES },
|
||||
{ "SEGMENTS", CFGTOK_SEGMENTS },
|
||||
{ "FORMATS", CFGTOK_FORMATS },
|
||||
{ "FEATURES", CFGTOK_FEATURES },
|
||||
};
|
||||
unsigned BlockTok;
|
||||
cfgtok_t BlockTok;
|
||||
|
||||
do {
|
||||
|
||||
@@ -947,23 +1126,27 @@ static void ParseConfig (void)
|
||||
switch (BlockTok) {
|
||||
|
||||
case CFGTOK_MEMORY:
|
||||
ParseMemory ();
|
||||
break;
|
||||
ParseMemory ();
|
||||
break;
|
||||
|
||||
case CFGTOK_FILES:
|
||||
ParseFiles ();
|
||||
break;
|
||||
ParseFiles ();
|
||||
break;
|
||||
|
||||
case CFGTOK_SEGMENTS:
|
||||
ParseSegments ();
|
||||
break;
|
||||
ParseSegments ();
|
||||
break;
|
||||
|
||||
case CFGTOK_FORMATS:
|
||||
ParseFormats ();
|
||||
ParseFormats ();
|
||||
break;
|
||||
|
||||
case CFGTOK_FEATURES:
|
||||
ParseFeatures ();
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ("Unexpected block token");
|
||||
FAIL ("Unexpected block token");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* ld65 */
|
||||
#include "global.h"
|
||||
#include "condes.h"
|
||||
#include "error.h"
|
||||
#include "fileio.h"
|
||||
#include "initfunc.h"
|
||||
#include "global.h"
|
||||
#include "objdata.h"
|
||||
#include "expr.h"
|
||||
#include "exports.h"
|
||||
@@ -202,17 +202,18 @@ static Export* NewExport (unsigned char Type, const char* Name, ObjData* Obj)
|
||||
|
||||
/* Initialize the fields */
|
||||
E->Next = 0;
|
||||
E->Flags = 0;
|
||||
E->Flags = 0;
|
||||
E->Obj = Obj;
|
||||
E->ImpCount = 0;
|
||||
E->ImpList = 0;
|
||||
E->Expr = 0;
|
||||
E->Type = Type;
|
||||
memset (E->ConDes, 0, sizeof (E->ConDes));
|
||||
if (Name) {
|
||||
E->Name = xstrdup (Name);
|
||||
} else {
|
||||
/* Name will get added later */
|
||||
E->Name = 0;
|
||||
/* Name will get added later */
|
||||
E->Name = 0;
|
||||
}
|
||||
|
||||
/* Return the new entry */
|
||||
@@ -229,9 +230,9 @@ void InsertExport (Export* E)
|
||||
Import* Imp;
|
||||
unsigned HashVal;
|
||||
|
||||
/* If this is an initializer, insert it into the initializer list */
|
||||
if (IS_EXP_INIT (E->Type)) {
|
||||
AddInitFunc (E);
|
||||
/* Insert the export into any condes tables if needed */
|
||||
if (IS_EXP_CONDES (E->Type)) {
|
||||
ConDesAddExport (E);
|
||||
}
|
||||
|
||||
/* Create a hash value for the given name */
|
||||
@@ -272,7 +273,7 @@ void InsertExport (Export* E)
|
||||
}
|
||||
} else {
|
||||
/* Duplicate entry, ignore it */
|
||||
Warning ("Duplicate external identifier: `%s'", L->Name);
|
||||
Warning ("Duplicate external identifier: `%s'", L->Name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -293,6 +294,7 @@ Export* ReadExport (FILE* F, ObjData* O)
|
||||
/* Read an export from a file */
|
||||
{
|
||||
unsigned char Type;
|
||||
unsigned ConDesCount;
|
||||
Export* E;
|
||||
|
||||
/* Read the type */
|
||||
@@ -301,6 +303,29 @@ Export* ReadExport (FILE* F, ObjData* O)
|
||||
/* Create a new export without a name */
|
||||
E = NewExport (Type, 0, O);
|
||||
|
||||
/* Read the constructor/destructor decls if we have any */
|
||||
ConDesCount = GET_EXP_CONDES_COUNT (Type);
|
||||
if (ConDesCount > 0) {
|
||||
|
||||
unsigned char ConDes[CD_TYPE_COUNT];
|
||||
unsigned I;
|
||||
|
||||
/* Read the data into temp storage */
|
||||
ReadData (F, ConDes, ConDesCount);
|
||||
|
||||
/* Re-order the data. In the file, each decl is encoded into a byte
|
||||
* which contains the type and the priority. In memory, we will use
|
||||
* an array of types which contain the priority. This array was
|
||||
* cleared by the constructor (NewExport), so we must only set the
|
||||
* fields that contain values.
|
||||
*/
|
||||
for (I = 0; I < ConDesCount; ++I) {
|
||||
unsigned ConDesType = CD_GET_TYPE (ConDes[I]);
|
||||
unsigned ConDesPrio = CD_GET_PRIO (ConDes[I]);
|
||||
E->ConDes[ConDesType] = ConDesPrio;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the name */
|
||||
E->Name = ReadStr (F);
|
||||
|
||||
@@ -562,7 +587,7 @@ void PrintExportMap (FILE* F)
|
||||
GetExportVal (E),
|
||||
E->ImpCount? 'R' : ' ',
|
||||
IS_EXP_ZP (E->Type)? 'Z' : ' ',
|
||||
IS_EXP_INIT (E->Type)? 'I' : ' ');
|
||||
IS_EXP_CONDES (E->Type)? 'I' : ' ');
|
||||
if (++Count == 2) {
|
||||
Count = 0;
|
||||
fprintf (F, "\n");
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* common */
|
||||
#include "cddefs.h"
|
||||
#include "exprdefs.h"
|
||||
#include "filepos.h"
|
||||
|
||||
@@ -81,7 +82,8 @@ struct Export {
|
||||
Import* ImpList; /* List of imports for this symbol */
|
||||
FilePos Pos; /* File position of definition */
|
||||
ExprNode* Expr; /* Expression (0 if not def'd) */
|
||||
unsigned char Type; /* Type of export */
|
||||
unsigned char Type; /* Type of export */
|
||||
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
|
||||
char* Name; /* Name - dynamically allocated */
|
||||
};
|
||||
|
||||
@@ -157,7 +159,7 @@ void CircularRefError (const Export* E);
|
||||
/* Print an error about a circular reference using to define the given export */
|
||||
|
||||
|
||||
|
||||
|
||||
/* End of exports.h */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -284,9 +284,12 @@ FilePos* ReadFilePos (FILE* F, FilePos* Pos)
|
||||
|
||||
void* ReadData (FILE* F, void* Data, unsigned Size)
|
||||
/* Read data from the file */
|
||||
{
|
||||
if (fread (Data, 1, Size, F) != Size) {
|
||||
Error ("Read error (file corrupt?)");
|
||||
{
|
||||
/* Explicitly allow reading zero bytes */
|
||||
if (Size > 0) {
|
||||
if (fread (Data, 1, Size, F) != Size) {
|
||||
Error ("Read error (file corrupt?)");
|
||||
}
|
||||
}
|
||||
return Data;
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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,10 +6,10 @@
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@@ -45,67 +45,77 @@
|
||||
|
||||
|
||||
/* Config file tokens */
|
||||
#define CFGTOK_NONE 0
|
||||
#define CFGTOK_INTCON 1
|
||||
#define CFGTOK_STRCON 2
|
||||
#define CFGTOK_IDENT 3
|
||||
#define CFGTOK_LCURLY 4
|
||||
#define CFGTOK_RCURLY 5
|
||||
#define CFGTOK_SEMI 6
|
||||
#define CFGTOK_COMMA 7
|
||||
#define CFGTOK_EQ 8
|
||||
#define CFGTOK_COLON 9
|
||||
#define CFGTOK_DOT 10
|
||||
#define CFGTOK_EOF 11
|
||||
typedef enum {
|
||||
CFGTOK_NONE,
|
||||
CFGTOK_INTCON,
|
||||
CFGTOK_STRCON,
|
||||
CFGTOK_IDENT,
|
||||
CFGTOK_LCURLY,
|
||||
CFGTOK_RCURLY,
|
||||
CFGTOK_SEMI,
|
||||
CFGTOK_COMMA,
|
||||
CFGTOK_EQ,
|
||||
CFGTOK_COLON,
|
||||
CFGTOK_DOT,
|
||||
CFGTOK_EOF,
|
||||
|
||||
/* Special identifiers */
|
||||
#define CFGTOK_MEMORY 20
|
||||
#define CFGTOK_FILES 21
|
||||
#define CFGTOK_SEGMENTS 22
|
||||
#define CFGTOK_FORMATS 23
|
||||
/* Special identifiers */
|
||||
CFGTOK_MEMORY,
|
||||
CFGTOK_FILES,
|
||||
CFGTOK_SEGMENTS,
|
||||
CFGTOK_FORMATS,
|
||||
CFGTOK_FEATURES,
|
||||
|
||||
#define CFGTOK_START 30
|
||||
#define CFGTOK_SIZE 31
|
||||
#define CFGTOK_TYPE 32
|
||||
#define CFGTOK_FILE 33
|
||||
#define CFGTOK_DEFINE 34
|
||||
#define CFGTOK_FILL 35
|
||||
#define CFGTOK_FILLVAL 36
|
||||
#define CFGTOK_EXPORT 37
|
||||
#define CFGTOK_IMPORT 38
|
||||
#define CFGTOK_OS 39
|
||||
#define CFGTOK_FORMAT 40
|
||||
CFGTOK_START,
|
||||
CFGTOK_SIZE,
|
||||
CFGTOK_TYPE,
|
||||
CFGTOK_FILE,
|
||||
CFGTOK_DEFINE,
|
||||
CFGTOK_FILL,
|
||||
CFGTOK_FILLVAL,
|
||||
CFGTOK_EXPORT,
|
||||
CFGTOK_IMPORT,
|
||||
CFGTOK_OS,
|
||||
CFGTOK_FORMAT,
|
||||
|
||||
#define CFGTOK_LOAD 50
|
||||
#define CFGTOK_RUN 51
|
||||
#define CFGTOK_ALIGN 52
|
||||
#define CFGTOK_OFFSET 53
|
||||
CFGTOK_LOAD,
|
||||
CFGTOK_RUN,
|
||||
CFGTOK_ALIGN,
|
||||
CFGTOK_OFFSET,
|
||||
|
||||
#define CFGTOK_RO 60
|
||||
#define CFGTOK_RW 61
|
||||
#define CFGTOK_BSS 62
|
||||
#define CFGTOK_ZP 63
|
||||
#define CFGTOK_WPROT 64
|
||||
CFGTOK_RO,
|
||||
CFGTOK_RW,
|
||||
CFGTOK_BSS,
|
||||
CFGTOK_ZP,
|
||||
CFGTOK_WPROT,
|
||||
|
||||
#define CFGTOK_O65 70
|
||||
#define CFGTOK_BIN 71
|
||||
CFGTOK_O65,
|
||||
CFGTOK_BIN,
|
||||
|
||||
#define CFGTOK_SMALL 80
|
||||
#define CFGTOK_LARGE 81
|
||||
CFGTOK_SMALL,
|
||||
CFGTOK_LARGE,
|
||||
|
||||
#define CFGTOK_TRUE 90
|
||||
#define CFGTOK_FALSE 91
|
||||
CFGTOK_TRUE,
|
||||
CFGTOK_FALSE,
|
||||
|
||||
#define CFGTOK_LUNIX 100
|
||||
#define CFGTOK_OSA65 101
|
||||
CFGTOK_LUNIX,
|
||||
CFGTOK_OSA65,
|
||||
|
||||
CFGTOK_CONDES,
|
||||
CFGTOK_SEGMENT,
|
||||
CFGTOK_LABEL,
|
||||
CFGTOK_CONSTRUCTOR,
|
||||
CFGTOK_DESTRUCTOR
|
||||
|
||||
} cfgtok_t;
|
||||
|
||||
|
||||
|
||||
/* Mapping table entry, special identifier --> token */
|
||||
typedef struct IdentTok_ IdentTok;
|
||||
struct IdentTok_ {
|
||||
const char* Ident; /* Identifier */
|
||||
unsigned Tok; /* Token for identifier */
|
||||
const char* Ident; /* Identifier */
|
||||
cfgtok_t Tok; /* Token for identifier */
|
||||
};
|
||||
#define ENTRY_COUNT(s) (sizeof (s) / sizeof (s [0]))
|
||||
|
||||
@@ -113,7 +123,7 @@ struct IdentTok_ {
|
||||
|
||||
/* Current token and attributes */
|
||||
#define CFG_MAX_IDENT_LEN 255
|
||||
extern unsigned CfgTok;
|
||||
extern cfgtok_t CfgTok;
|
||||
extern char CfgSVal [CFG_MAX_IDENT_LEN+1];
|
||||
extern unsigned long CfgIVal;
|
||||
|
||||
@@ -138,7 +148,7 @@ void CfgError (const char* Format, ...) attribute((format(printf,1,2)));
|
||||
void CfgNextTok (void);
|
||||
/* Read the next token from the input stream */
|
||||
|
||||
void CfgConsume (unsigned T, const char* Msg);
|
||||
void CfgConsume (cfgtok_t T, const char* Msg);
|
||||
/* Skip a token, print an error message if not found */
|
||||
|
||||
void CfgConsumeSemi (void);
|
||||
@@ -196,4 +206,4 @@ void CfgCloseInput (void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user