1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00

More work on the implementation of spans.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5150 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2011-08-11 16:52:52 +00:00
parent efc59ff27b
commit 9ecccaa69d

View File

@ -292,6 +292,7 @@ struct ScopeInfo {
unsigned Id; /* Id of label symbol */
SymInfo* Info; /* Pointer to label symbol */
} Label;
Collection SpanInfoList; /* List of spans for this scope */
char Name[1]; /* Name of scope */
};
@ -314,6 +315,7 @@ struct SpanInfo {
unsigned Id; /* Id of segment */
SegInfo* Info; /* Pointer to segment */
} Seg;
Collection* ScopeInfoList; /* Scopes for this span */
};
/* Internally used symbol info struct */
@ -594,6 +596,14 @@ static Collection* CollInit (Collection* C)
static Collection* CollNew (void)
/* Allocate a new collection, initialize and return it */
{
return CollInit (xmalloc (sizeof (Collection)));
}
static void CollDone (Collection* C)
/* Free the data for a collection. This will not free the data contained in
* the collection.
@ -612,6 +622,18 @@ static void CollDone (Collection* C)
static void CollFree (Collection* C)
/* Free a dynamically allocated collection */
{
/* Accept NULL pointers */
if (C) {
xfree (C->Items);
xfree (C);
}
}
static unsigned CollCount (const Collection* C)
/* Return the number of items in the collection */
{
@ -852,7 +874,7 @@ static void CollQuickSort (Collection* C, int Lo, int Hi,
void CollSort (Collection* C, int (*Compare) (const void*, const void*))
static void CollSort (Collection* C, int (*Compare) (const void*, const void*))
/* Sort the collection using the given compare function. */
{
if (C->Count > 1) {
@ -1472,7 +1494,8 @@ static ScopeInfo* NewScopeInfo (const StrBuf* Name)
/* Allocate memory */
ScopeInfo* S = xmalloc (sizeof (ScopeInfo) + SB_GetLen (Name));
/* Initialize the name */
/* Initialize the fields as necessary */
CollInit (&S->SpanInfoList);
memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
/* Return it */
@ -1484,6 +1507,7 @@ static ScopeInfo* NewScopeInfo (const StrBuf* Name)
static void FreeScopeInfo (ScopeInfo* S)
/* Free a ScopeInfo struct */
{
CollDone (&S->SpanInfoList);
xfree (S);
}
@ -1623,8 +1647,12 @@ static int CompareSegInfoByName (const void* L, const void* R)
static SpanInfo* NewSpanInfo (void)
/* Create a new SpanInfo struct, intialize and return it */
{
/* Allocate memory and return it */
return xmalloc (sizeof (SpanInfo));
/* Allocate memory */
SpanInfo* S = xmalloc (sizeof (SpanInfo));
/* Initialize and return it */
S->ScopeInfoList = 0;
return S;
}
@ -1632,6 +1660,7 @@ static SpanInfo* NewSpanInfo (void)
static void FreeSpanInfo (SpanInfo* S)
/* Free a SpanInfo struct */
{
CollFree (S->ScopeInfoList);
xfree (S);
}
@ -2900,6 +2929,7 @@ static void ParseScope (InputData* D)
StrBuf Name = STRBUF_INITIALIZER;
unsigned ModId = CC65_INV_ID;
unsigned ParentId = CC65_INV_ID;
Collection SpanIds = COLLECTION_INITIALIZER;
unsigned SymId = CC65_INV_ID;
ScopeInfo* S;
enum {
@ -2910,8 +2940,9 @@ static void ParseScope (InputData* D)
ibName = 0x004,
ibParentId = 0x008,
ibSize = 0x010,
ibSymId = 0x020,
ibType = 0x040,
ibSpanId = 0x020,
ibSymId = 0x040,
ibType = 0x080,
ibRequired = ibId | ibModId | ibName,
} InfoBits = ibNone;
@ -2927,8 +2958,8 @@ static void ParseScope (InputData* D)
/* Something we know? */
if (D->Tok != TOK_ID && D->Tok != TOK_MODULE &&
D->Tok != TOK_NAME && D->Tok != TOK_PARENT &&
D->Tok != TOK_SIZE && D->Tok != TOK_SYM &&
D->Tok != TOK_TYPE) {
D->Tok != TOK_SIZE && D->Tok != TOK_SPAN &&
D->Tok != TOK_SYM && D->Tok != TOK_TYPE) {
/* Try smart error recovery */
if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
@ -2996,6 +3027,21 @@ static void ParseScope (InputData* D)
NextToken (D);
break;
case TOK_SPAN:
while (1) {
if (!IntConstFollows (D)) {
goto ErrorExit;
}
CollAppendId (&SpanIds, (unsigned) D->IVal);
NextToken (D);
if (D->Tok != TOK_PLUS) {
break;
}
NextToken (D);
}
InfoBits |= ibSpanId;
break;
case TOK_SYM:
if (!IntConstFollows (D)) {
goto ErrorExit;
@ -3049,7 +3095,7 @@ static void ParseScope (InputData* D)
goto ErrorExit;
}
/* Create the scope info */
/* Create the scope info ... */
S = NewScopeInfo (&Name);
S->Id = Id;
S->Type = Type;
@ -3059,10 +3105,12 @@ static void ParseScope (InputData* D)
S->Label.Id = SymId;
/* ... and remember it */
CollMove (&S->SpanInfoList, &SpanIds);
CollReplaceExpand (&D->Info->ScopeInfoById, S, Id);
ErrorExit:
/* Entry point in case of errors */
CollDone (&SpanIds);
SB_Done (&Name);
return;
}
@ -3245,6 +3293,134 @@ ErrorExit:
static void ParseSpan (InputData* D)
/* Parse a SPAN line */
{
unsigned Id = 0;
cc65_addr Start = 0;
cc65_addr Size = 0;
unsigned SegId = CC65_INV_ID;
SpanInfo* S;
enum {
ibNone = 0x000,
ibId = 0x01,
ibSegId = 0x02,
ibSize = 0x04,
ibStart = 0x08,
ibRequired = ibId | ibSegId | ibSize | ibStart,
} InfoBits = ibNone;
/* Skip the SEGMENT token */
NextToken (D);
/* More stuff follows */
while (1) {
Token Tok;
/* Something we know? */
if (D->Tok != TOK_ID && D->Tok != TOK_SEGMENT &&
D->Tok != TOK_SIZE && D->Tok != TOK_START) {
/* Try smart error recovery */
if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
UnknownKeyword (D);
continue;
}
/* Done */
break;
}
/* Remember the token, skip it, check for equal */
Tok = D->Tok;
NextToken (D);
if (!ConsumeEqual (D)) {
goto ErrorExit;
}
/* Check what the token was */
switch (Tok) {
case TOK_ID:
if (!IntConstFollows (D)) {
goto ErrorExit;
}
Id = D->IVal;
InfoBits |= ibId;
NextToken (D);
break;
case TOK_SEGMENT:
if (!IntConstFollows (D)) {
goto ErrorExit;
}
SegId = D->IVal;
InfoBits |= ibSegId;
NextToken (D);
break;
case TOK_SIZE:
if (!IntConstFollows (D)) {
goto ErrorExit;
}
Size = D->IVal;
NextToken (D);
InfoBits |= ibSize;
break;
case TOK_START:
if (!IntConstFollows (D)) {
goto ErrorExit;
}
Start = (cc65_addr) D->IVal;
NextToken (D);
InfoBits |= ibStart;
break;
default:
/* NOTREACHED */
UnexpectedToken (D);
goto ErrorExit;
}
/* Comma or done */
if (D->Tok != TOK_COMMA) {
break;
}
NextToken (D);
}
/* Check for end of line */
if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) {
UnexpectedToken (D);
SkipLine (D);
goto ErrorExit;
}
/* Check for required and/or matched information */
if ((InfoBits & ibRequired) != ibRequired) {
ParseError (D, CC65_ERROR, "Required attributes missing");
goto ErrorExit;
}
/* Create the span info and remember it */
S = NewSpanInfo ();
S->Id = Id;
S->Seg.Id = SegId;
S->Offs = Start;
S->Size = Size;
CollReplaceExpand (&D->Info->SpanInfoById, S, Id);
ErrorExit:
/* Entry point in case of errors */
return;
}
static void ParseSym (InputData* D)
/* Parse a SYM line */
{
@ -3935,7 +4111,7 @@ static void ProcessModInfo (InputData* D)
static void ProcessScopeInfo (InputData* D)
/* Postprocess scope infos */
{
unsigned I;
unsigned I, J;
/* Walk over all scopes. Resolve the ids and add the scopes to the list
* of scopes for a module.
@ -3984,6 +4160,33 @@ static void ProcessScopeInfo (InputData* D)
} else {
S->Label.Info = CollAt (&D->Info->SymInfoById, S->Label.Id);
}
/* Resolve the spans ids */
for (J = 0; I < CollCount (&S->SpanInfoList); ++J) {
/* Get the id of this span */
unsigned SpanId = CollIdAt (&S->SpanInfoList, J);
if (SpanId >= CollCount (&D->Info->SpanInfoById)) {
ParseError (D,
CC65_ERROR,
"Invalid span id %u for scope with id %u",
SpanId, S->Id);
CollReplace (&S->SpanInfoList, 0, J);
} else {
/* Get a pointer to the span */
SpanInfo* SP = CollAt (&D->Info->SpanInfoById, SpanId);
/* Replace the id by the pointer */
CollReplace (&S->SpanInfoList, SP, J);
/* Insert a backpointer into the span */
if (SP->ScopeInfoList == 0) {
SP->ScopeInfoList = CollNew ();
}
CollAppend (SP->ScopeInfoList, S);
}
}
}
/* Walk over all modules and sort the scopes by name */
@ -4008,6 +4211,32 @@ static void ProcessSegInfo (InputData* D)
static void ProcessSpanInfo (InputData* D)
/* Postprocess span infos */
{
unsigned I;
/* Walk over all spans and resolve the ids */
for (I = 0; I < CollCount (&D->Info->SpanInfoById); ++I) {
/* Get this span info */
SpanInfo* S = CollAt (&D->Info->SpanInfoById, I);
/* Resolve the segment */
if (S->Seg.Id >= CollCount (&D->Info->SegInfoById)) {
ParseError (D,
CC65_ERROR,
"Invalid segment id %u for span with id %u",
S->Seg.Id, S->Id);
S->Seg.Info = 0;
} else {
S->Seg.Info = CollAt (&D->Info->SegInfoById, S->Seg.Id);
}
}
}
static void ProcessSymInfo (InputData* D)
/* Postprocess symbol infos */
{
@ -4214,6 +4443,10 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
ParseSegment (&D);
break;
case TOK_SPAN:
ParseSpan (&D);
break;
case TOK_SYM:
ParseSym (&D);
break;
@ -4262,6 +4495,7 @@ CloseAndExit:
ProcessModInfo (&D);
ProcessScopeInfo (&D);
ProcessSegInfo (&D);
ProcessSpanInfo (&D);
ProcessSymInfo (&D);
#if DEBUG