From 9ecccaa69dc5d4585e52df3cc09a0a3096f9a9ce Mon Sep 17 00:00:00 2001 From: uz Date: Thu, 11 Aug 2011 16:52:52 +0000 Subject: [PATCH] More work on the implementation of spans. git-svn-id: svn://svn.cc65.org/cc65/trunk@5150 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 254 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 244 insertions(+), 10 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index c1170dc8b..db53c526b 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -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 -- 2.39.5