git-svn-id: svn://svn.cc65.org/cc65/trunk@2092 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2003-04-27 15:31:00 +00:00
parent 251547f028
commit 8bff858b09
6 changed files with 293 additions and 239 deletions

View File

@@ -50,6 +50,7 @@
#include "chip.h"
#include "error.h"
#include "global.h"
#include "memory.h"
#include "scanner.h"
#include "config.h"
@@ -67,11 +68,11 @@ static Collection Locations;
/* One memory location */
typedef struct Location Location;
struct Location {
unsigned long Start; /* Start of memory location */
unsigned long End; /* End memory location */
Collection Attributes; /* Attributes given */
unsigned Line; /* Line in config file */
unsigned Col; /* Column in config file */
unsigned Start; /* Start of memory location */
unsigned End; /* End memory location */
Collection Attributes; /* Attributes given */
unsigned Line; /* Line in config file */
unsigned Col; /* Column in config file */
};
@@ -94,7 +95,7 @@ static CfgData* NewCfgData (void)
CfgData* D = xmalloc (sizeof (CfgData) + AttrLen);
/* Initialize the fields */
D->Type = CfgDataInvalid;
D->Type = CfgDataInvalid;
D->Line = CfgErrorLine;
D->Col = CfgErrorCol;
memcpy (D->Attr, CfgSVal, AttrLen+1);
@@ -105,6 +106,30 @@ static CfgData* NewCfgData (void)
static void FreeCfgData (CfgData* D)
/* Free a config data structure */
{
if (D->Type == CfgDataString) {
/* Free the string value */
xfree (D->V.SVal);
}
/* Free the structure */
xfree (D);
}
static void CfgDataCheckType (const CfgData* D, unsigned Type)
/* Check the config data type */
{
if (D->Type != Type) {
Error ("%s(%u): Attribute `%s' has invalid type",
CfgGetName (), D->Line, D->Attr);
}
}
/*****************************************************************************/
/* struct Location */
/*****************************************************************************/
@@ -150,9 +175,9 @@ static int CmpLocations (void* Data attribute ((unused)),
static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return it. Return NULL if the
* attribute was not found.
static int LocationFindAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return its index. Return -1 if
* the attribute was not found.
*/
{
unsigned I;
@@ -166,12 +191,26 @@ static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
/* Compare the name */
if (StrCaseCmp (D->Attr, AttrName) == 0) {
/* Found */
return D;
return I;
}
}
/* Not found */
return 0;
return -1;
}
static int LocationGetAttr (const Location* L, const char* AttrName)
/* Find the attribute with the given name and return it. Call Error() if the
* attribute was not found.
*/
{
int I = LocationFindAttr (L, AttrName);
if (I < 0) {
Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
}
return I;
}
@@ -180,40 +219,17 @@ static int LocationIsMirror (const Location* L)
/* Return true if the given location is a mirror of another one. */
{
/* Find the "mirror" attribute */
return (LocationFindAttr (L, "mirror") != 0);
return (LocationFindAttr (L, "mirror") >= 0);
}
/*****************************************************************************/
/* Code */
/* Code */
/*****************************************************************************/
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
/* Check if the item is already defined. Print an error if so. If not, set
* the marker that we have a definition now.
*/
{
if (*Flags & Mask) {
CfgError ("%s is already defined", Name);
}
*Flags |= Mask;
}
static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
/* Check that a mandatory attribute was given */
{
if ((Attr & Mask) == 0) {
CfgError ("%s attribute is missing", Name);
}
}
static void ParseMemory (void)
/* Parse a MEMORY section */
{
@@ -312,19 +328,106 @@ static void ParseMemory (void)
if (LocationIsMirror (L)) {
const CfgData* D;
if (CollCount (&L->Attributes) > 1) {
Error ("%s(%u): Location at address $%06lX is a mirror "
Error ("%s(%u): Location at address $%06X is a mirror "
"but has attributes", CfgGetName(), L->Line, L->Start);
}
D = CollConstAt (&L->Attributes, 0);
if (D->Type != CfgDataNumber) {
Error ("%s(%u): Mirror attribute is not an integer",
CfgGetName (), L->Line);
}
CfgDataCheckType (D, CfgDataNumber);
}
/* Remember this entry */
Last = L;
}
/* Now create the chip instances. Since we can only mirror existing chips,
* we will first create all real chips and the mirrors in a second run.
*/
for (I = 0; I < CollCount (&Locations); ++I) {
int Index;
CfgData* D;
unsigned Range; /* Address range for this chip */
ChipInstance* CI;
/* Get this location */
Location* L = CollAtUnchecked (&Locations, I);
/* Skip mirrors */
if (LocationIsMirror (L)) {
continue;
}
/* The chip must have an attribute "name" of type string */
Index = LocationGetAttr (L, "name");
D = CollAt (&L->Attributes, Index);
CfgDataCheckType (D, CfgDataString);
/* Remove the "name" attribute from the attribute list */
CollDelete (&L->Attributes, Index);
/* Create the chip instance for the address range */
Range = L->End - L->Start;
CI = NewChipInstance (D->V.SVal, L->Start, Range, &L->Attributes);
/* Delete the "name" attribute */
FreeCfgData (D);
/* Assign the chip instance to memory */
MemAssignChip (CI, L->Start, Range);
}
/* Create the mirrors */
for (I = 0; I < CollCount (&Locations); ++I) {
const CfgData* D;
unsigned MirrorAddr; /* Mirror address */
unsigned Range; /* Address range for this chip */
unsigned Offs; /* Offset of the mirror */
const ChipInstance* CI; /* Original chip instance */
ChipInstance* MCI; /* Mirrored chip instance */
/* Get this location */
const Location* L = CollAtUnchecked (&Locations, I);
/* Skip non mirrors */
if (!LocationIsMirror (L)) {
continue;
}
/* Calculate the address range */
Range = L->End - L->Start;
/* Get the mirror address */
D = CollConstAt (&L->Attributes, 0);
MirrorAddr = (unsigned) D->V.IVal;
/* For simplicity, get the chip instance we're mirroring from the
* memory, instead of searching for the range in the list.
*/
CI = MemGetChip (MirrorAddr);
if (CI == 0) {
/* We are mirroring an unassigned address */
Error ("%s(%u): Mirroring an unassigned address",
CfgGetName (), L->Line);
}
/* Make sure we're mirroring the correct chip */
CHECK (MirrorAddr >= CI->Addr && MirrorAddr < CI->Addr + CI->Size);
/* Calculate the offset of the mirror */
Offs = MirrorAddr - CI->Addr;
/* Check if the mirror range is ok */
if (Offs + Range > CI->Size) {
Error ("%s(%u): Mirror range is too large", CfgGetName (), L->Line);
}
/* Clone the chip instance for the new location */
MCI = MirrorChipInstance (CI, L->Start - Offs);
/* Assign the chip instance to memory */
MemAssignChip (MCI, L->Start, Range);
}
}