From 067f6d2e27dded3bf5bd0ba647a301f0cae430aa Mon Sep 17 00:00:00 2001 From: uz Date: Mon, 8 Aug 2011 21:07:13 +0000 Subject: [PATCH] Much more work reading the new information. git-svn-id: svn://svn.cc65.org/cc65/trunk@5138 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 708 ++++++++++++++++++++++++++++++++---------- 1 file changed, 552 insertions(+), 156 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 1d806b446..076461cae 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -95,37 +95,6 @@ struct LineInfoList { LineInfoListEntry* List; /* Dynamic array with entries */ }; - - -/* Data structure containing information from the debug info file. A pointer - * to this structure is passed as handle to callers from the outside. - */ -typedef struct DbgInfo DbgInfo; -struct DbgInfo { - - /* First we have all items in collections sorted by id. The ids are - * continous, so an access by id is almost as cheap as an array access. - * The collections are also used when the objects are deleted, so they're - * actually the ones that "own" the items. - */ - Collection FileInfoById; /* File infos sorted by id */ - Collection LibInfoById; /* Library infos sorted by id */ - Collection ModInfoById; /* Module infos sorted by id */ - Collection ScopeInfoById; /* Scope infos sorted by id */ - Collection SegInfoById; /* Segment infos sorted by id */ - Collection SymInfoById; /* Symbol infos sorted by id */ - - /* Collections with other sort criteria */ - Collection FileInfoByName; /* File infos sorted by name */ - Collection LineInfos; /* List of all line infos */ - Collection SegInfoByName; /* Segment infos sorted by name */ - Collection SymInfoByName; /* Symbol infos sorted by name */ - Collection SymInfoByVal; /* Symbol infos sorted by value */ - - /* Other stuff */ - LineInfoList LineInfoByAddr; /* Line infos sorted by unique address */ -}; - /* Input tokens */ typedef enum { @@ -145,9 +114,12 @@ typedef enum { TOK_ABSOLUTE = TOK_FIRST_KEYWORD, /* ABSOLUTE keyword */ TOK_ADDRSIZE, /* ADDRSIZE keyword */ TOK_COUNT, /* COUNT keyword */ + TOK_ENUM, /* ENUM keyword */ TOK_EQUATE, /* EQUATE keyword */ TOK_FILE, /* FILE keyword */ + TOK_GLOBAL, /* GLOBAL keyword */ TOK_ID, /* ID keyword */ + TOK_INFO, /* INFO keyword */ TOK_LABEL, /* LABEL keyword */ TOK_LIBRARY, /* LIBRARY keyword */ TOK_LINE, /* LINE keyword */ @@ -167,6 +139,7 @@ typedef enum { TOK_SEGMENT, /* SEGMENT keyword */ TOK_SIZE, /* SIZE keyword */ TOK_START, /* START keyword */ + TOK_STRUCT, /* STRUCT keyword */ TOK_SYM, /* SYM keyword */ TOK_TYPE, /* TYPE keyword */ TOK_VALUE, /* VALUE keyword */ @@ -177,6 +150,37 @@ typedef enum { TOK_IDENT, /* To catch unknown keywords */ } Token; + + +/* Data structure containing information from the debug info file. A pointer + * to this structure is passed as handle to callers from the outside. + */ +typedef struct DbgInfo DbgInfo; +struct DbgInfo { + + /* First we have all items in collections sorted by id. The ids are + * continous, so an access by id is almost as cheap as an array access. + * The collections are also used when the objects are deleted, so they're + * actually the ones that "own" the items. + */ + Collection FileInfoById; /* File infos sorted by id */ + Collection LibInfoById; /* Library infos sorted by id */ + Collection ModInfoById; /* Module infos sorted by id */ + Collection ScopeInfoById; /* Scope infos sorted by id */ + Collection SegInfoById; /* Segment infos sorted by id */ + Collection SymInfoById; /* Symbol infos sorted by id */ + + /* Collections with other sort criteria */ + Collection FileInfoByName; /* File infos sorted by name */ + Collection LineInfos; /* List of all line infos */ + Collection SegInfoByName; /* Segment infos sorted by name */ + Collection SymInfoByName; /* Symbol infos sorted by name */ + Collection SymInfoByVal; /* Symbol infos sorted by value */ + + /* Other stuff */ + LineInfoList LineInfoByAddr; /* Line infos sorted by unique address */ +}; + /* Data used when parsing the debug info file */ typedef struct InputData InputData; struct InputData { @@ -198,7 +202,6 @@ struct InputData { }; /* Typedefs for the item structures. Do also serve as forwards */ -typedef struct IdStruct IdStruct; typedef struct FileInfo FileInfo; typedef struct LibInfo LibInfo; typedef struct LineInfo LineInfo; @@ -207,20 +210,15 @@ typedef struct ScopeInfo ScopeInfo; typedef struct SegInfo SegInfo; typedef struct SymInfo SymInfo; -/* The C standard guarantees that layout of structures with identical members - * is identical. To save some code, all structures below have an unsigned - * named Id as first member. We will use the following struct in the functions - * for sorting to save some code. - */ -struct IdStruct { - unsigned Id; /* Id of structure */ -}; - /* Internally used file info struct */ struct FileInfo { unsigned Id; /* Id of file */ unsigned long Size; /* Size of file */ unsigned long MTime; /* Modification time */ + union { + unsigned Id; /* Id of module */ + ModInfo* Info; /* Pointer to module info */ + } Mod; Collection LineInfoByLine; /* Line infos sorted by line */ char FileName[1]; /* Name of file with full path */ }; @@ -268,10 +266,18 @@ struct ScopeInfo { cc65_scope_type Type; /* Type of scope */ cc65_size Size; /* Size of scope */ unsigned Flags; /* Scope flags */ + union { + unsigned Id; /* Id of module */ + ModInfo* Info; /* Pointer to module info */ + } Mod; union { unsigned Id; /* Id of parent scope */ ScopeInfo* Scope; /* Pointer to parent scope */ } Parent; + union { + unsigned Id; /* Id of label symbol */ + SymInfo* Info; /* Pointer to label symbol */ + } Sym; char ScopeName[1]; /* Name of scope */ }; @@ -692,6 +698,39 @@ static void CollInsert (Collection* C, void* Item, unsigned Index) +static void CollReplaceExpand (Collection* C, void* Item, unsigned Index) +/* If Index is a valid index for the collection, replace the item at this + * position by the one passed. If the collection is too small, expand it, + * filling unused pointers with NULL, then add the new item at the given + * position. + */ +{ + if (Index < C->Count) { + /* Collection is already large enough */ + C->Items[Index] = Item; + } else { + /* Must expand the collection */ + unsigned Size = C->Size; + if (Size == 0) { + Size = 8; + } + while (Index >= Size) { + Size *= 2; + } + CollGrow (C, Size); + + /* Fill up unused slots with NULL */ + while (C->Count < Index) { + C->Items[C->Count++] = 0; + } + + /* Fill in the item */ + C->Items[C->Count++] = Item; + } +} + + + static void CollAppend (Collection* C, void* Item) /* Append an item to the end of the collection */ { @@ -889,37 +928,19 @@ static void DumpData (InputData* D) -/*****************************************************************************/ -/* struct IdStruct */ -/*****************************************************************************/ - - - -static int CompareById (const void* L, const void* R) -/* Helper function to sort structures in a collection by id */ -{ - return ((int)((const IdStruct*) L)->Id) - ((int)((const IdStruct*) R)->Id); -} - - - /*****************************************************************************/ /* File info */ /*****************************************************************************/ -static FileInfo* NewFileInfo (const StrBuf* FileName, unsigned Id, - unsigned long Size, unsigned long MTime) +static FileInfo* NewFileInfo (const StrBuf* FileName) /* Create a new FileInfo struct and return it */ { /* Allocate memory */ FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (FileName)); /* Initialize it */ - F->Id = Id; - F->Size = Size; - F->MTime = MTime; InitCollection (&F->LineInfoByLine); memcpy (F->FileName, SB_GetConstBuf (FileName), SB_GetLen (FileName) + 1); @@ -1735,22 +1756,25 @@ static void NextToken (InputData* D) /* Read the next token from the input stream */ { static const struct KeywordEntry { - const char Keyword[16]; + const char Keyword[12]; Token Tok; } KeywordTable[] = { { "abs", TOK_ABSOLUTE }, { "addrsize", TOK_ADDRSIZE }, { "count", TOK_COUNT }, + { "enum", TOK_ENUM }, { "equ", TOK_EQUATE }, { "file", TOK_FILE }, + { "global", TOK_GLOBAL }, { "id", TOK_ID }, + { "info", TOK_INFO }, { "lab", TOK_LABEL }, { "lib", TOK_LIBRARY }, { "line", TOK_LINE }, { "long", TOK_LONG }, { "major", TOK_MAJOR }, { "minor", TOK_MINOR }, - { "module", TOK_MODULE }, + { "mod", TOK_MODULE }, { "mtime", TOK_MTIME }, { "name", TOK_NAME }, { "oname", TOK_OUTPUTNAME }, @@ -1763,6 +1787,7 @@ static void NextToken (InputData* D) { "seg", TOK_SEGMENT }, { "size", TOK_SIZE }, { "start", TOK_START }, + { "struct", TOK_STRUCT }, { "sym", TOK_SYM }, { "type", TOK_TYPE }, { "val", TOK_VALUE }, @@ -1971,6 +1996,7 @@ static void ParseFile (InputData* D) unsigned Id = 0; unsigned long Size = 0; unsigned long MTime = 0; + unsigned ModId = CC65_INV_ID; StrBuf FileName = STRBUF_INITIALIZER; FileInfo* F; enum { @@ -1979,7 +2005,8 @@ static void ParseFile (InputData* D) ibFileName = 0x02, ibSize = 0x04, ibMTime = 0x08, - ibRequired = ibId | ibFileName | ibSize | ibMTime, + ibModId = 0x10, + ibRequired = ibId | ibFileName | ibSize | ibMTime | ibModId, } InfoBits = ibNone; /* Skip the FILE token */ @@ -1991,8 +2018,9 @@ static void ParseFile (InputData* D) Token Tok; /* Something we know? */ - if (D->Tok != TOK_ID && D->Tok != TOK_MTIME && - D->Tok != TOK_NAME && D->Tok != TOK_SIZE) { + if (D->Tok != TOK_ID && D->Tok != TOK_MODULE && + D->Tok != TOK_MTIME && D->Tok != TOK_NAME && + D->Tok != TOK_SIZE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { @@ -2032,6 +2060,21 @@ static void ParseFile (InputData* D) InfoBits |= ibMTime; break; + case TOK_MODULE: + while (1) { + if (!IntConstFollows (D)) { + goto ErrorExit; + } + ModId = D->IVal; + InfoBits |= ibModId; + NextToken (D); + if (D->Tok != TOK_PLUS) { + break; + } + NextToken (D); + } + break; + case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; @@ -2079,7 +2122,12 @@ static void ParseFile (InputData* D) } /* Create the file info and remember it */ - F = NewFileInfo (&FileName, Id, Size, MTime); + F = NewFileInfo (&FileName); + F->Id = Id; + F->Size = Size; + F->MTime = MTime; + F->Mod.Id = ModId; + CollReplaceExpand (&D->Info->FileInfoById, F, Id); CollAppend (&D->Info->FileInfoByName, F); ErrorExit: @@ -2090,6 +2138,210 @@ ErrorExit: +static void ParseInfo (InputData* D) +/* Parse an INFO line */ +{ + /* Skip the INFO token */ + NextToken (D); + + /* More stuff follows */ + while (1) { + + Token Tok; + + /* Something we know? */ + if (D->Tok != TOK_FILE && D->Tok != TOK_LIBRARY && + D->Tok != TOK_LINE && D->Tok != TOK_MODULE && + D->Tok != TOK_SCOPE && D->Tok != TOK_SEGMENT && + D->Tok != TOK_SYM) { + + /* 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, check for an integer + * constant. + */ + Tok = D->Tok; + NextToken (D); + if (!ConsumeEqual (D)) { + goto ErrorExit; + } + if (!IntConstFollows (D)) { + goto ErrorExit; + } + + /* Check what the token was */ + switch (Tok) { + + case TOK_FILE: + CollGrow (&D->Info->FileInfoById, D->IVal); + break; + + case TOK_LIBRARY: + CollGrow (&D->Info->LibInfoById, D->IVal); + break; + + case TOK_LINE: + /*CollGrow (&D->Info->LineInfoById, D->IVal);*/ + break; + + case TOK_MODULE: + CollGrow (&D->Info->ModInfoById, D->IVal); + break; + + case TOK_SCOPE: + CollGrow (&D->Info->ScopeInfoById, D->IVal); + break; + + case TOK_SEGMENT: + CollGrow (&D->Info->SegInfoById, D->IVal); + break; + + case TOK_SYM: + CollGrow (&D->Info->SymInfoById, D->IVal); + break; + + default: + /* NOTREACHED */ + UnexpectedToken (D); + goto ErrorExit; + + } + + /* Skip the number */ + NextToken (D); + + /* 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; + } + +ErrorExit: + /* Entry point in case of errors */ + return; +} + + + +static void ParseLibrary (InputData* D) +/* Parse a LIBRARY line */ +{ + unsigned Id = 0; + StrBuf Name = STRBUF_INITIALIZER; + LibInfo* L; + enum { + ibNone = 0x00, + ibId = 0x01, + ibName = 0x02, + ibRequired = ibId | ibName, + } InfoBits = ibNone; + + /* Skip the LIBRARY token */ + NextToken (D); + + /* More stuff follows */ + while (1) { + + Token Tok; + + /* Something we know? */ + if (D->Tok != TOK_ID && D->Tok != TOK_NAME) { + + /* 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_NAME: + if (!StrConstFollows (D)) { + goto ErrorExit; + } + SB_Copy (&Name, &D->SVal); + SB_Terminate (&Name); + InfoBits |= ibName; + NextToken (D); + 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 information */ + if ((InfoBits & ibRequired) != ibRequired) { + ParseError (D, CC65_ERROR, "Required attributes missing"); + goto ErrorExit; + } + + /* Create the library info and remember it */ + L = NewLibInfo (&Name); + L->Id = Id; + CollReplaceExpand (&D->Info->LibInfoById, L, Id); + +ErrorExit: + /* Entry point in case of errors */ + SB_Done (&Name); + return; +} + + + static void ParseLine (InputData* D) /* Parse a LINE line */ { @@ -2249,6 +2501,144 @@ ErrorExit: +static void ParseModule (InputData* D) +/* Parse a MODULE line */ +{ + /* Most of the following variables are initialized with a value that is + * overwritten later. This is just to avoid compiler warnings. + */ + unsigned Id = CC65_INV_ID; + StrBuf Name = STRBUF_INITIALIZER; + unsigned FileId = CC65_INV_ID; + unsigned LibId = CC65_INV_ID; + ModInfo* M; + enum { + ibNone = 0x000, + + ibFileId = 0x001, + ibId = 0x002, + ibName = 0x004, + ibLibId = 0x008, + + ibRequired = ibId | ibName | ibFileId, + } InfoBits = ibNone; + + /* Skip the MODULE token */ + NextToken (D); + + /* More stuff follows */ + while (1) { + + Token Tok; + + /* Something we know? */ + if (D->Tok != TOK_FILE && D->Tok != TOK_ID && + D->Tok != TOK_NAME && D->Tok != TOK_LIBRARY) { + + /* 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_FILE: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + FileId = D->IVal; + InfoBits |= ibFileId; + NextToken (D); + break; + + case TOK_ID: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Id = D->IVal; + InfoBits |= ibId; + NextToken (D); + break; + + case TOK_NAME: + if (!StrConstFollows (D)) { + goto ErrorExit; + } + SB_Copy (&Name, &D->SVal); + SB_Terminate (&Name); + InfoBits |= ibName; + NextToken (D); + break; + + case TOK_LIBRARY: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + LibId = D->IVal; + InfoBits |= ibLibId; + NextToken (D); + 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 scope info */ + M = NewModInfo (&Name); + M->File.Id = FileId; + M->Id = Id; + M->Lib.Id = LibId; + + /* ... and remember it */ + CollReplaceExpand (&D->Info->ModInfoById, M, Id); + +ErrorExit: + /* Entry point in case of errors */ + SB_Done (&Name); + return; +} + + + + + + static void ParseScope (InputData* D) /* Parse a SCOPE line */ { @@ -2259,18 +2649,22 @@ static void ParseScope (InputData* D) cc65_scope_type Type = CC65_SCOPE_MODULE; cc65_size Size = 0; StrBuf Name = STRBUF_INITIALIZER; - unsigned Parent = CC65_INV_ID; + unsigned ModId = CC65_INV_ID; + unsigned ParentId = CC65_INV_ID; + unsigned SymId = CC65_INV_ID; ScopeInfo* S; enum { ibNone = 0x000, ibId = 0x001, - ibName = 0x002, - ibParent = 0x004, - ibSize = 0x008, - ibType = 0x010, - - ibRequired = ibId | ibName | ibParent | ibType, + ibModId = 0x002, + ibName = 0x004, + ibParentId = 0x008, + ibSize = 0x010, + ibSymId = 0x020, + ibType = 0x040, + + ibRequired = ibId | ibModId | ibName, } InfoBits = ibNone; /* Skip the SCOPE token */ @@ -2282,8 +2676,9 @@ static void ParseScope (InputData* D) Token Tok; /* Something we know? */ - if (D->Tok != TOK_ID && D->Tok != TOK_NAME && - D->Tok != TOK_PARENT && D->Tok != TOK_SIZE && + 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) { /* Try smart error recovery */ @@ -2315,6 +2710,15 @@ static void ParseScope (InputData* D) NextToken (D); break; + case TOK_MODULE: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + ModId = D->IVal; + InfoBits |= ibModId; + NextToken (D); + break; + case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; @@ -2329,9 +2733,9 @@ static void ParseScope (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - Size = D->IVal; + ParentId = D->IVal; NextToken (D); - InfoBits |= ibParent; + InfoBits |= ibParentId; break; case TOK_SIZE: @@ -2343,14 +2747,22 @@ static void ParseScope (InputData* D) NextToken (D); break; + case TOK_SYM: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + SymId = D->IVal; + NextToken (D); + InfoBits |= ibSymId; + break; + case TOK_TYPE: switch (D->Tok) { - case TOK_EQUATE: - Type = CC65_SYM_EQUATE; - break; - case TOK_LABEL: - Type = CC65_SYM_LABEL; - break; + case TOK_GLOBAL: Type = CC65_SCOPE_GLOBAL; break; + case TOK_FILE: Type = CC65_SCOPE_MODULE; break; + case TOK_SCOPE: Type = CC65_SCOPE_SCOPE; break; + case TOK_STRUCT: Type = CC65_SCOPE_STRUCT; break; + case TOK_ENUM: Type = CC65_SCOPE_ENUM; break; default: ParseError (D, CC65_ERROR, "Unknown value for attribute \"type\""); @@ -2393,10 +2805,12 @@ static void ParseScope (InputData* D) S->Id = Id; S->Type = Type; S->Size = Size; - S->Parent.Id = Parent; + S->Mod.Id = ModId; + S->Parent.Id = ParentId; + S->Sym.Id = SymId; /* ... and remember it */ - CollAppend (&D->Info->ScopeInfoById, S); + CollReplaceExpand (&D->Info->ScopeInfoById, S, Id); ErrorExit: /* Entry point in case of errors */ @@ -2570,6 +2984,7 @@ static void ParseSegment (InputData* D) /* Create the segment info and remember it */ S = NewSegInfo (&SegName, Id, Start, Size, &OutputName, OutputOffs); + CollReplaceExpand (&D->Info->SegInfoById, S, Id); CollAppend (&D->Info->SegInfoByName, S); ErrorExit: @@ -2587,12 +3002,12 @@ static void ParseSym (InputData* D) /* Most of the following variables are initialized with a value that is * overwritten later. This is just to avoid compiler warnings. */ - unsigned File = CC65_INV_ID; + unsigned FileId = CC65_INV_ID; unsigned Id = CC65_INV_ID; StrBuf Name = STRBUF_INITIALIZER; - unsigned Parent = CC65_INV_ID; - unsigned Scope = CC65_INV_ID; - unsigned Segment = CC65_INV_ID; + unsigned ParentId = CC65_INV_ID; + unsigned ScopeId = CC65_INV_ID; + unsigned SegId = CC65_INV_ID; cc65_size Size = 0; cc65_symbol_type Type = CC65_SYM_EQUATE; long Value = 0; @@ -2602,18 +3017,17 @@ static void ParseSym (InputData* D) ibNone = 0x000, ibAddrSize = 0x001, - ibFile = 0x002, + ibFileId = 0x002, ibId = 0x004, - ibParent = 0x008, - ibScope = 0x010, - ibSegment = 0x020, + ibParentId = 0x008, + ibScopeId = 0x010, + ibSegId = 0x020, ibSize = 0x040, ibName = 0x080, ibType = 0x100, ibValue = 0x200, - ibRequired = ibAddrSize | ibId | ibScope | ibName | - ibType | ibValue, + ibRequired = ibAddrSize | ibId | ibName | ibType | ibValue, } InfoBits = ibNone; /* Skip the SYM token */ @@ -2660,8 +3074,8 @@ static void ParseSym (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - File = D->IVal; - InfoBits |= ibFile; + FileId = D->IVal; + InfoBits |= ibFileId; NextToken (D); break; @@ -2688,26 +3102,26 @@ static void ParseSym (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - Parent = D->IVal; + ParentId = D->IVal; NextToken (D); - InfoBits |= ibParent; + InfoBits |= ibParentId; break; case TOK_SCOPE: if (!IntConstFollows (D)) { goto ErrorExit; } - Scope = D->IVal; + ScopeId = D->IVal; NextToken (D); - InfoBits |= ibScope; + InfoBits |= ibScopeId; break; case TOK_SEGMENT: if (!IntConstFollows (D)) { goto ErrorExit; } - Segment = (unsigned) D->IVal; - InfoBits |= ibSegment; + SegId = (unsigned) D->IVal; + InfoBits |= ibSegId; NextToken (D); break; @@ -2722,12 +3136,9 @@ static void ParseSym (InputData* D) case TOK_TYPE: switch (D->Tok) { - case TOK_EQUATE: - Type = CC65_SYM_EQUATE; - break; - case TOK_LABEL: - Type = CC65_SYM_LABEL; - break; + case TOK_EQUATE: Type = CC65_SYM_EQUATE; break; + case TOK_LABEL: Type = CC65_SYM_LABEL; break; + default: ParseError (D, CC65_ERROR, "Unknown value for attribute \"type\""); @@ -2773,6 +3184,11 @@ static void ParseSym (InputData* D) ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } + if ((InfoBits & (ibScopeId | ibParentId)) == 0 || + (InfoBits & (ibScopeId | ibParentId)) == (ibScopeId | ibParentId)) { + ParseError (D, CC65_ERROR, "Only one of \"parent\", \"scope\" must be specified"); + goto ErrorExit; + } /* Create the symbol info */ S = NewSymInfo (&Name); @@ -2780,12 +3196,12 @@ static void ParseSym (InputData* D) S->Type = Type; S->Value = Value; S->Size = Size; - S->Segment = Segment; - S->Scope = Scope; - S->Parent = Parent; + S->Segment = SegId; + S->Scope = ScopeId; + S->Parent = ParentId; /* Remember it */ - CollAppend (&D->Info->SymInfoById, S); + CollReplaceExpand (&D->Info->SymInfoById, S, Id); CollAppend (&D->Info->SymInfoByName, S); CollAppend (&D->Info->SymInfoByVal, S); @@ -2999,22 +3415,8 @@ static FileInfo* FindFileInfoById (DbgInfo* D, unsigned Id) static void ProcessSegInfo (InputData* D) /* Postprocess segment infos */ { - unsigned I; - - /* Get pointers to the segment info collections */ - Collection* SegInfoByName = &D->Info->SegInfoByName; - Collection* SegInfoById = &D->Info->SegInfoById; - /* Sort the segment infos by name */ - CollSort (SegInfoByName, CompareSegInfoByName); - - /* Copy all items over to the collection that will get sorted by id */ - for (I = 0; I < CollCount (SegInfoByName); ++I) { - CollAppend (SegInfoById, CollAt (SegInfoByName, I)); - } - - /* Sort this collection */ - CollSort (SegInfoById, CompareById); + CollSort (&D->Info->SegInfoByName, CompareSegInfoByName); } @@ -3022,22 +3424,8 @@ static void ProcessSegInfo (InputData* D) static void ProcessFileInfo (InputData* D) /* Postprocess file infos */ { - unsigned I; - - /* Get pointers to the file info collections */ - Collection* FileInfoByName = &D->Info->FileInfoByName; - Collection* FileInfoById = &D->Info->FileInfoById; - - /* First, sort the file infos, so we can do a binary search */ - CollSort (FileInfoByName, CompareFileInfoByName); - - /* Copy the file infos to another collection that will be sorted by id */ - for (I = 0; I < CollCount (FileInfoByName); ++I) { - CollAppend (FileInfoById, CollAt (FileInfoByName, I)); - } - - /* Sort this collection */ - CollSort (FileInfoById, CompareById); + /* Sort the file infos by name, so we can do a binary search */ + CollSort (&D->Info->FileInfoByName, CompareFileInfoByName); } @@ -3225,15 +3613,9 @@ static int FindLineInfoByLine (Collection* LineInfos, cc65_line Line, static void ProcessSymInfo (InputData* D) /* Postprocess symbol infos */ { - /* Get pointers to the symbol info collections */ - Collection* SymInfoById = &D->Info->SymInfoById; - Collection* SymInfoByName = &D->Info->SymInfoByName; - Collection* SymInfoByVal = &D->Info->SymInfoByVal; - /* Sort the symbol infos */ - CollSort (SymInfoById, CompareById); - CollSort (SymInfoByName, CompareSymInfoByName); - CollSort (SymInfoByVal, CompareSymInfoByVal); + CollSort (&D->Info->SymInfoByName, CompareSymInfoByName); + CollSort (&D->Info->SymInfoByVal, CompareSymInfoByVal); } @@ -3367,9 +3749,6 @@ static void ProcessScopeInfo (InputData* D) /* Get pointers to the scope info collections */ Collection* ScopeInfoById = &D->Info->ScopeInfoById; - /* Sort the scope infos */ - CollSort (ScopeInfoById, CompareById); - /* Walk over all scope infos and replace the parent scope id by a pointer * to the parent scope. */ @@ -3379,7 +3758,12 @@ static void ProcessScopeInfo (InputData* D) ScopeInfo* S = CollAt (ScopeInfoById, I); /* Replace the parent id by a pointer */ - S->Parent.Scope = CollAt (ScopeInfoById, S->Parent.Id); + if (S->Parent.Id != CC65_INV_ID) { + S->Parent.Scope = CollAt (ScopeInfoById, S->Parent.Id); + } else { + /* No parent */ + S->Parent.Scope = 0; + } } } @@ -3523,10 +3907,22 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) ParseFile (&D); break; + case TOK_INFO: + ParseInfo (&D); + break; + + case TOK_LIBRARY: + ParseLibrary (&D); + break; + case TOK_LINE: ParseLine (&D); break; + case TOK_MODULE: + ParseModule (&D); + break; + case TOK_SCOPE: ParseScope (&D); break; -- 2.39.5