From f204ec956a79a4754a0928f2dfeccd09ec6c5710 Mon Sep 17 00:00:00 2001 From: uz Date: Tue, 30 Aug 2011 13:19:28 +0000 Subject: [PATCH] Parse csym lines in the debug info file. No api functions til now. git-svn-id: svn://svn.cc65.org/cc65/trunk@5289 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 288 +++++++++++++++++++++++++++++++++++++++++- src/dbginfo/dbginfo.h | 57 ++++++++- 2 files changed, 338 insertions(+), 7 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index d61949a39..bf4c44801 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -128,10 +128,12 @@ typedef enum { TOK_ADDRSIZE, /* ADDRSIZE keyword */ TOK_AUTO, /* AUTO keyword */ TOK_COUNT, /* COUNT keyword */ + TOK_CSYM, /* CSYM keyword */ TOK_DEF, /* DEF keyword */ TOK_ENUM, /* ENUM keyword */ TOK_EQUATE, /* EQUATE keyword */ TOK_EXPORT, /* EXPORT keyword */ + TOK_EXTERN, /* EXTERN keyword */ TOK_FILE, /* FILE keyword */ TOK_FUNC, /* FUNC keyword */ TOK_GLOBAL, /* GLOBAL keyword */ @@ -147,12 +149,15 @@ typedef enum { TOK_MODULE, /* MODULE keyword */ TOK_MTIME, /* MTIME keyword */ TOK_NAME, /* NAME keyword */ + TOK_OFFS, /* OFFS keyword */ TOK_OUTPUTNAME, /* OUTPUTNAME keyword */ TOK_OUTPUTOFFS, /* OUTPUTOFFS keyword */ TOK_PARENT, /* PARENT keyword */ TOK_REF, /* REF keyword */ + TOK_REGISTER, /* REGISTER keyword */ TOK_RO, /* RO keyword */ TOK_RW, /* RW keyword */ + TOK_SC, /* SC keyword */ TOK_SCOPE, /* SCOPE keyword */ TOK_SEGMENT, /* SEGMENT keyword */ TOK_SIZE, /* SIZE keyword */ @@ -182,6 +187,7 @@ struct DbgInfo { * The collections are also used when the objects are deleted, so they're * actually the ones that "own" the items. */ + Collection CSymInfoById; /* C symbol infos sorted by id */ Collection FileInfoById; /* File infos sorted by id */ Collection LibInfoById; /* Library infos sorted by id */ Collection LineInfoById; /* Line infos sorted by id */ @@ -229,6 +235,7 @@ struct InputData { }; /* Typedefs for the item structures. Do also serve as forwards */ +typedef struct CSymInfo CSymInfo; typedef struct FileInfo FileInfo; typedef struct LibInfo LibInfo; typedef struct LineInfo LineInfo; @@ -239,6 +246,27 @@ typedef struct SpanInfo SpanInfo; typedef struct SymInfo SymInfo; typedef struct TypeInfo TypeInfo; +/* Internally used c symbol info struct */ +struct CSymInfo { + unsigned Id; /* Id of file */ + unsigned short Kind; /* Kind of C symbol */ + unsigned short SC; /* Storage class of C symbol */ + int Offs; /* Offset */ + union { + unsigned Id; /* Id of attached asm symbol */ + SymInfo* Info; /* Pointer to attached asm symbol */ + } Sym; + union { + unsigned Id; /* Id of type */ + TypeInfo* Info; /* Pointer to type */ + } Type; + union { + unsigned Id; /* Id of scope */ + ScopeInfo* Info; /* Pointer to scope */ + } Scope; + char Name[1]; /* Name of file with full path */ +}; + /* Internally used file info struct */ struct FileInfo { unsigned Id; /* Id of file */ @@ -1135,6 +1163,46 @@ static void UnknownKeyword (InputData* D) +/*****************************************************************************/ +/* C symbol info */ +/*****************************************************************************/ + + + +static CSymInfo* NewCSymInfo (const StrBuf* Name) +/* Create a new CSymInfo struct and return it */ +{ + /* Allocate memory */ + CSymInfo* S = xmalloc (sizeof (CSymInfo) + SB_GetLen (Name)); + + /* Initialize it */ + memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); + + /* Return it */ + return S; +} + + + +static void FreeCSymInfo (CSymInfo* S) +/* Free a CSymInfo struct */ +{ + /* Free the structure itself */ + xfree (S); +} + + + +static int CompareCSymInfoByName (const void* L, const void* R) +/* Helper function to sort c symbol infos in a collection by name */ +{ + /* Sort by symbol name */ + return strcmp (((const CSymInfo*) L)->Name, + ((const CSymInfo*) R)->Name); +} + + + /*****************************************************************************/ /* File info */ /*****************************************************************************/ @@ -2286,6 +2354,7 @@ static DbgInfo* NewDbgInfo (const char* FileName) DbgInfo* Info = xmalloc (sizeof (DbgInfo) + Len); /* Initialize it */ + CollInit (&Info->CSymInfoById); CollInit (&Info->FileInfoById); CollInit (&Info->LibInfoById); CollInit (&Info->LineInfoById); @@ -2322,6 +2391,9 @@ static void FreeDbgInfo (DbgInfo* Info) unsigned I; /* First, free the items in the collections */ + for (I = 0; I < CollCount (&Info->CSymInfoById); ++I) { + FreeCSymInfo (CollAt (&Info->CSymInfoById, I)); + } for (I = 0; I < CollCount (&Info->FileInfoById); ++I) { FreeFileInfo (CollAt (&Info->FileInfoById, I)); } @@ -2351,6 +2423,7 @@ static void FreeDbgInfo (DbgInfo* Info) } /* Free the memory used by the id collections */ + CollDone (&Info->CSymInfoById); CollDone (&Info->FileInfoById); CollDone (&Info->LibInfoById); CollDone (&Info->LineInfoById); @@ -2425,10 +2498,12 @@ static void NextToken (InputData* D) { "addrsize", TOK_ADDRSIZE }, { "auto", TOK_AUTO }, { "count", TOK_COUNT }, + { "csym", TOK_CSYM }, { "def", TOK_DEF }, { "enum", TOK_ENUM }, { "equ", TOK_EQUATE }, { "exp", TOK_EXPORT }, + { "ext", TOK_EXTERN }, { "file", TOK_FILE }, { "func", TOK_FUNC }, { "global", TOK_GLOBAL }, @@ -2444,12 +2519,15 @@ static void NextToken (InputData* D) { "mod", TOK_MODULE }, { "mtime", TOK_MTIME }, { "name", TOK_NAME }, + { "offs", TOK_OFFS }, { "oname", TOK_OUTPUTNAME }, { "ooffs", TOK_OUTPUTOFFS }, { "parent", TOK_PARENT }, { "ref", TOK_REF }, + { "reg", TOK_REGISTER }, { "ro", TOK_RO }, { "rw", TOK_RW }, + { "sc", TOK_SC }, { "scope", TOK_SCOPE }, { "seg", TOK_SEGMENT }, { "size", TOK_SIZE }, @@ -2660,6 +2738,196 @@ static void ConsumeEOL (InputData* D) +static void ParseCSym (InputData* D) +/* Parse a CSYM line */ +{ + /* Most of the following variables are initialized with a value that is + * overwritten later. This is just to avoid compiler warnings. + */ + unsigned Id = 0; + StrBuf Name = STRBUF_INITIALIZER; + int Offs = 0; + cc65_csym_sc SC = CC65_CSYM_AUTO; + unsigned ScopeId = 0; + unsigned SymId = CC65_INV_ID; + unsigned TypeId = CC65_INV_ID; + CSymInfo* S; + enum { + ibNone = 0x0000, + + ibId = 0x0001, + ibOffs = 0x0002, + ibName = 0x0004, + ibSC = 0x0008, + ibScopeId = 0x0010, + ibSymId = 0x0020, + ibType = 0x0040, + + ibRequired = ibId | ibName | ibSC | ibScopeId | ibType, + } InfoBits = ibNone; + + /* Skip the CSYM token */ + NextToken (D); + + /* More stuff follows */ + while (1) { + + Token Tok; + + /* Something we know? */ + if (D->Tok != TOK_ID && D->Tok != TOK_NAME && + D->Tok != TOK_OFFS && D->Tok != TOK_SC && + D->Tok != TOK_SCOPE && D->Tok != TOK_SYM && + D->Tok != TOK_TYPE) { + + /* 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; + NextToken (D); + InfoBits |= ibId; + break; + + case TOK_NAME: + if (!StrConstFollows (D)) { + goto ErrorExit; + } + SB_Copy (&Name, &D->SVal); + SB_Terminate (&Name); + InfoBits |= ibName; + NextToken (D); + break; + + case TOK_OFFS: + Offs = 1; + if (D->Tok == TOK_MINUS) { + Offs = -1; + NextToken (D); + } + if (!IntConstFollows (D)) { + goto ErrorExit; + } + Offs *= (int) D->IVal; + InfoBits |= ibOffs; + NextToken (D); + break; + + case TOK_SC: + switch (D->Tok) { + case TOK_AUTO: SC = CC65_CSYM_AUTO; break; + case TOK_EXTERN: SC = CC65_CSYM_EXTERN; break; + case TOK_REGISTER: SC = CC65_CSYM_REG; break; + case TOK_STATIC: SC = CC65_CSYM_STATIC; break; + default: + ParseError (D, CC65_ERROR, "Invalid storage class token"); + break; + } + InfoBits |= ibSC; + NextToken (D); + break; + + case TOK_SCOPE: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + ScopeId = D->IVal; + NextToken (D); + InfoBits |= ibScopeId; + break; + + case TOK_SYM: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + SymId = D->IVal; + NextToken (D); + InfoBits |= ibSymId; + break; + + case TOK_TYPE: + if (!IntConstFollows (D)) { + goto ErrorExit; + } + TypeId = D->IVal; + NextToken (D); + InfoBits |= ibType; + 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; + } + + /* Symbol only valid if storage class not auto */ + if (((InfoBits & ibSymId) != 0) != (SC != CC65_CSYM_AUTO)) { + ParseError (D, CC65_ERROR, "Only non auto symbols can have a symbol attached"); + goto ErrorExit; + } + + /* Create the symbol info */ + S = NewCSymInfo (&Name); + S->Id = Id; + S->Kind = CC65_CSYM_VAR; + S->SC = SC; + S->Offs = Offs; + S->Sym.Id = SymId; + S->Type.Id = TypeId; + S->Scope.Id = ScopeId; + + /* Remember it */ + CollReplaceExpand (&D->Info->CSymInfoById, S, Id); + +ErrorExit: + /* Entry point in case of errors */ + SB_Done (&Name); + return; +} + + + static void ParseFile (InputData* D) /* Parse a FILE line */ { @@ -2821,11 +3089,11 @@ static void ParseInfo (InputData* D) 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_SPAN && D->Tok != TOK_SYM && - D->Tok != TOK_TYPE) { + if (D->Tok != TOK_CSYM && 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_SPAN && + D->Tok != TOK_SYM && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { @@ -2852,9 +3120,13 @@ static void ParseInfo (InputData* D) /* Check what the token was */ switch (Tok) { + case TOK_CSYM: + CollGrow (&D->Info->CSymInfoById, D->IVal); + break; + case TOK_FILE: CollGrow (&D->Info->FileInfoById, D->IVal); - CollGrow (&D->Info->FileInfoByName, D->IVal); + CollGrow (&D->Info->FileInfoByName, D->IVal); break; case TOK_LIBRARY: @@ -5219,6 +5491,10 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) switch (D.Tok) { + case TOK_CSYM: + ParseCSym (&D); + break; + case TOK_FILE: ParseFile (&D); break; diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index c001cbcb8..a2b8cf4ba 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -108,6 +108,61 @@ void cc65_free_dbginfo (cc65_dbginfo Handle); +/*****************************************************************************/ +/* C Symbols */ +/*****************************************************************************/ + + + +/* C symbol kinds */ +typedef enum { + CC65_CSYM_FUNC, + CC65_CSYM_VAR +} cc65_csym_kind; + +/* C object storage classes */ +typedef enum { + CC65_CSYM_AUTO, /* Auto = on stack */ + CC65_CSYM_REG, /* Register = in register bank */ + CC65_CSYM_STATIC, /* Static = static storage */ + CC65_CSYM_EXTERN /* Extern = static storage + external visibility */ +} cc65_csym_sc; + +/* C symbol information */ +typedef struct cc65_csymdata cc65_csymdata; +struct cc65_csymdata { + unsigned csym_id; /* The internal c symbol id */ + unsigned char csym_kind; /* Kind of c symbol */ + unsigned char csym_sc; /* Storage class of c symbol */ + int csym_offs; /* Offset for auto and register */ + unsigned symbol_id; /* Attached asm symbol if any */ + unsigned scope_id; /* Scope of c symbol */ + const char* csym_name; /* Name of the symbol */ +}; + +typedef struct cc65_csyminfo cc65_csyminfo; +struct cc65_csyminfo { + unsigned count; /* Number of data sets that follow */ + cc65_csymdata data[1]; /* Data sets, number is dynamic */ +}; + + + +const cc65_csyminfo* cc65_get_csymlist (cc65_dbginfo handle); +/* Return a list of all c symbols */ + +const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo handle, unsigned id); +/* Return information about a c symbol with a specific id. The function + * returns NULL if the id is invalid (no such c symbol) and otherwise a + * cc65_csyminfo structure with one entry that contains the requested + * symbol information. + */ + +void cc65_free_csyminfo (cc65_dbginfo handle, const cc65_csyminfo* info); +/* Free a c symbol info record */ + + + /*****************************************************************************/ /* Libraries */ /*****************************************************************************/ @@ -624,7 +679,7 @@ void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data); /* Allow usage from C++ */ -#ifdef __cplusplus +#ifdef __cplusplus } #endif