From 4b1c5e4157ddca5abe8edc7b5e6336906411c29d Mon Sep 17 00:00:00 2001 From: uz Date: Thu, 5 Aug 2010 21:00:36 +0000 Subject: [PATCH] First working version with complete API for line information. git-svn-id: svn://svn.cc65.org/cc65/trunk@4784 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/dbginfo/dbginfo.c | 437 ++++++++++++++++++++++++++++++--------- src/dbginfo/dbginfo.h | 42 ++-- src/dbginfo/dbgtest.c | 41 +++- src/dbginfo/make/gcc.mak | 4 +- 4 files changed, 403 insertions(+), 121 deletions(-) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 0b6b720d9..8997b1b0b 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -81,20 +82,12 @@ static const Collection EmptyCollection = COLLECTION_INITIALIZER; -/* ### Parseerror */ -enum { - CC65_WARNING, - CC65_ERROR, -}; - /* 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 { - Collection FileInfo; /* Collection with file infos */ - Collection LineInfo; /* Collection with line infos */ - + Collection FileInfos; /* Collection with file infos */ }; /* Input tokens */ @@ -119,6 +112,9 @@ enum Token { TOK_FILE, /* FILE keyword */ TOK_LABEL, /* LABEL keyword */ TOK_LINE, /* LINE keyword */ + TOK_LONG, /* LONG_keyword */ + TOK_MAJOR, /* MAJOR keyword */ + TOK_MINOR, /* MINOR keyword */ TOK_MTIME, /* MTIME keyword */ TOK_RANGE, /* RANGE keyword */ TOK_RO, /* RO keyword */ @@ -131,15 +127,17 @@ enum Token { TOK_VALUE, /* VALUE keyword */ TOK_VERSION, /* VERSION keyword */ TOK_ZEROPAGE, /* ZEROPAGE keyword */ + + TOK_IDENT, /* To catch unknown keywords */ }; /* Data used when parsing the debug info file */ typedef struct InputData InputData; struct InputData { const char* FileName; /* Name of input file */ - unsigned long Line; /* Current line number */ + cc65_line Line; /* Current line number */ unsigned Col; /* Current column number */ - unsigned long SLine; /* Line number at start of token */ + cc65_line SLine; /* Line number at start of token */ unsigned SCol; /* Column number at start of token */ unsigned Errors; /* Number of errors */ FILE* F; /* Input file */ @@ -148,6 +146,9 @@ struct InputData { unsigned long IVal; /* Integer constant */ StrBuf SVal; /* String constant */ cc65_errorfunc Error; /* Function called in case of errors */ + unsigned MajorVersion; /* Major version number */ + unsigned MinorVersion; /* Minor version number */ + Collection LineInfos; /* Line information */ DbgInfo* Info; /* Pointer to debug info */ }; @@ -156,15 +157,18 @@ typedef struct FileInfo FileInfo; struct FileInfo { unsigned long Size; /* Size of file */ unsigned long MTime; /* Modification time */ + cc65_addr Start; /* Start address of line infos */ + cc65_addr End; /* End address of line infos */ + Collection LineInfos; /* Line infos for this file */ char FileName[1]; /* Name of file with full path */ }; /* Internally used line info struct */ typedef struct LineInfo LineInfo; struct LineInfo { - unsigned long Start; /* Start of data range */ - unsigned long End; /* End of data range */ - unsigned long Line; /* Line number */ + cc65_addr Start; /* Start of data range */ + cc65_addr End; /* End of data range */ + cc65_line Line; /* Line number */ FileInfo* FileInfo; /* Pointer to file info */ char FileName[1]; /* Name of file */ }; @@ -200,9 +204,7 @@ static void* xmalloc (size_t Size) P = malloc (Size); /* Check for errors */ - if (P == 0) { - /* ####### */ - } + assert (P != 0); } /* Return a pointer to the block */ @@ -442,6 +444,30 @@ static void* CollAt (Collection* C, unsigned Index) +static void* CollFirst (Collection* C) +/* Return the first item in a collection */ +{ + /* We must have at least one entry */ + assert (C->Count > 0); + + /* Return the element */ + return C->Items[0]; +} + + + +static void* CollLast (Collection* C) +/* Return the last item in a collection */ +{ + /* We must have at least one entry */ + assert (C->Count > 0); + + /* Return the element */ + return C->Items[C->Count-1]; +} + + + static void CollDelete (Collection* C, unsigned Index) /* Remove the item with the given index from the collection. This will not * free the item itself, just the pointer. All items with higher indices @@ -528,90 +554,117 @@ void CollSort (Collection* C, int (*Compare) (const void*, const void*)) /*****************************************************************************/ -/* File info */ +/* Line info */ /*****************************************************************************/ -static FileInfo* NewFileInfo (const StrBuf* FileName) -/* Create a new FileInfo struct and return it */ +static LineInfo* NewLineInfo (const StrBuf* FileName) +/* Create a new LineInfo struct and return it */ { /* Allocate memory */ - FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (FileName)); + LineInfo* L = xmalloc (sizeof (LineInfo) + SB_GetLen (FileName)); /* Initialize it */ - F->Size = 0; - F->MTime = 0; - memcpy (F->FileName, SB_GetConstBuf (FileName), SB_GetLen (FileName) + 1); + L->Start = 0; + L->End = 0; + L->Line = 0; + L->FileInfo = 0; + memcpy (L->FileName, SB_GetConstBuf (FileName), SB_GetLen (FileName) + 1); /* Return it */ - return F; + return L; } -static void FreeFileInfo (FileInfo* F) -/* Free a FileInfo struct */ +static void FreeLineInfo (LineInfo* L) +/* Free a LineInfo struct */ { - xfree (F); + xfree (L); } -static int CompareFileInfo (const void* L, const void* R) -/* Helper function to sort file infos in a collection */ +static LineInfo* PreenLineInfo (LineInfo* L, FileInfo* F) +/* Replace the name by file information */ { - /* Sort by file name */ - return strcmp (((const FileInfo*) L)->FileName, - ((const FileInfo*) R)->FileName); + /* Shrink the LineInfo struct removing the FfileName field */ + L = xrealloc (L, sizeof (*L) - 1); + + /* Set the FileInfo pointer instead */ + L->FileInfo = F; + + /* Return the result */ + return L; +} + + + +static int CompareLineInfo (const void* L, const void* R) +/* Helper function to sort line infos in a collection */ +{ + /* Sort by start of range */ + if (((const LineInfo*) L)->Start > ((const LineInfo*) R)->Start) { + return 1; + } else if (((const LineInfo*) L)->Start < ((const LineInfo*) R)->Start) { + return -1; + } else { + return 0; + } } /*****************************************************************************/ -/* Line info */ +/* File info */ /*****************************************************************************/ -static LineInfo* NewLineInfo (const StrBuf* FileName) -/* Create a new LineInfo struct and return it */ +static FileInfo* NewFileInfo (const StrBuf* FileName) +/* Create a new FileInfo struct and return it */ { /* Allocate memory */ - LineInfo* L = xmalloc (sizeof (LineInfo) + SB_GetLen (FileName)); + FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (FileName)); /* Initialize it */ - L->Start = 0; - L->End = 0; - L->Line = 0; - L->FileInfo = 0; - memcpy (L->FileName, SB_GetConstBuf (FileName), SB_GetLen (FileName) + 1); + F->Size = 0; + F->MTime = 0; + F->Start = ~(cc65_addr)0; + F->End = 0; + InitCollection (&F->LineInfos); + memcpy (F->FileName, SB_GetConstBuf (FileName), SB_GetLen (FileName) + 1); /* Return it */ - return L; + return F; } -static void FreeLineInfo (LineInfo* L) -/* Free a LineInfo struct */ +static void FreeFileInfo (FileInfo* F) +/* Free a FileInfo struct */ { - xfree (L); -} + unsigned I; + /* Walk through the collection with line infos and delete them */ + for (I = 0; I < CollCount (&F->LineInfos); ++I) { + FreeLineInfo (CollAt (&F->LineInfos, I)); + } + DoneCollection (&F->LineInfos); + /* Free the file info structure itself */ + xfree (F); +} -static LineInfo* PreenLineInfo (LineInfo* L, FileInfo* F) -/* Replace the name by file information */ -{ - /* Shrink the LineInfo struct removing the FfileName field */ - L = xrealloc (L, sizeof (*L) - 1); - /* Set the FileInfo pointer instead */ - L->FileInfo = F; - /* Return the result */ - return L; +static int CompareFileInfo (const void* L, const void* R) +/* Helper function to sort file infos in a collection */ +{ + /* Sort by file name */ + return strcmp (((const FileInfo*) L)->FileName, + ((const FileInfo*) R)->FileName); } @@ -629,8 +682,7 @@ static DbgInfo* NewDbgInfo (void) DbgInfo* Info = xmalloc (sizeof (DbgInfo)); /* Initialize it */ - InitCollection (&Info->FileInfo); - InitCollection (&Info->LineInfo); + InitCollection (&Info->FileInfos); /* Return it */ return Info; @@ -644,16 +696,10 @@ static void FreeDbgInfo (DbgInfo* Info) unsigned I; /* Free file info */ - for (I = 0; I < CollCount (&Info->FileInfo); ++I) { - FreeFileInfo (CollAt (&Info->FileInfo, I)); + for (I = 0; I < CollCount (&Info->FileInfos); ++I) { + FreeFileInfo (CollAt (&Info->FileInfos, I)); } - DoneCollection (&Info->FileInfo); - - /* Free line info */ - for (I = 0; I < CollCount (&Info->LineInfo); ++I) { - FreeLineInfo (CollAt (&Info->LineInfo, I)); - } - DoneCollection (&Info->LineInfo); + DoneCollection (&Info->FileInfos); /* Free the structure itself */ xfree (Info); @@ -667,7 +713,7 @@ static void FreeDbgInfo (DbgInfo* Info) -static void ParseError (InputData* D, unsigned Type, const char* Msg, ...) +static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...) /* Call the user supplied parse error function */ { va_list ap; @@ -782,6 +828,9 @@ static void NextToken (InputData* D) { "file", TOK_FILE }, { "label", TOK_LABEL }, { "line", TOK_LINE }, + { "long", TOK_LONG }, + { "major", TOK_MAJOR }, + { "minor", TOK_MINOR }, { "mtime", TOK_MTIME }, { "range", TOK_RANGE }, { "ro", TOK_RO }, @@ -826,8 +875,7 @@ static void NextToken (InputData* D) sizeof (KeywordTable[0]), (int (*)(const void*, const void*)) strcmp); if (Entry == 0) { - ParseError (D, CC65_ERROR, "Unknown keyword `%s'", SB_GetConstBuf (&D->SVal)); - D->Tok = TOK_INVALID; + D->Tok = TOK_IDENT; } else { D->Tok = Entry->Tok; } @@ -1061,7 +1109,7 @@ static void ParseFile (InputData* D) } /* Remember the file info */ - CollAppend (&D->Info->FileInfo, F); + CollAppend (&D->Info->FileInfos, F); /* Done */ return; @@ -1124,7 +1172,7 @@ static void ParseLine (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - L->Start = D->IVal; + L->Start = (cc65_addr) D->IVal; NextToken (D); if (!ConsumeMinus (D)) { goto ErrorExit; @@ -1132,7 +1180,7 @@ static void ParseLine (InputData* D) if (!IntConstFollows (D)) { goto ErrorExit; } - L->Start = D->IVal; + L->End = (cc65_addr) D->IVal; NextToken (D); InfoBits |= Range; break; @@ -1156,7 +1204,7 @@ static void ParseLine (InputData* D) } /* Remember the line info */ - CollAppend (&D->Info->LineInfo, L); + CollAppend (&D->LineInfos, L); /* Done */ return; @@ -1195,11 +1243,72 @@ static void ParseSym (InputData* D) static void ParseVersion (InputData* D) /* Parse a VERSION line */ { + enum { None = 0x00, Major = 0x01, Minor = 0x02 } InfoBits = None; + /* Skip the VERSION token */ NextToken (D); - /* ### */ - SkipLine (D); + /* More stuff follows */ + while (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { + + switch (D->Tok) { + + case TOK_MAJOR: + NextToken (D); + if (!ConsumeEqual (D)) { + goto ErrorExit; + } + if (!IntConstFollows (D)) { + goto ErrorExit; + } + D->MajorVersion = D->IVal; + NextToken (D); + InfoBits |= Major; + break; + + case TOK_MINOR: + NextToken (D); + if (!ConsumeEqual (D)) { + goto ErrorExit; + } + if (!IntConstFollows (D)) { + goto ErrorExit; + } + D->MinorVersion = D->IVal; + NextToken (D); + InfoBits |= Minor; + break; + + default: + UnexpectedToken (D); + SkipLine (D); + goto ErrorExit; + } + + /* Comma follows before next attribute */ + if (D->Tok == TOK_COMMA) { + NextToken (D); + } else if (D->Tok == TOK_EOL || D->Tok == TOK_EOF) { + break; + } else { + UnexpectedToken (D); + goto ErrorExit; + } + } + + /* Check for required information */ + if ((InfoBits & Major) == None) { + MissingAttribute (D, "major"); + goto ErrorExit; + } + if ((InfoBits & Minor) == None) { + MissingAttribute (D, "minor"); + goto ErrorExit; + } + +ErrorExit: + /* Entry point in case of errors */ + return; } @@ -1214,7 +1323,7 @@ static FileInfo* FindFileInfo (InputData* D, const char* FileName) /* Find the FileInfo for a given file name */ { /* Get a pointer to the file info collection */ - Collection* FileInfos = &D->Info->FileInfo; + Collection* FileInfos = &D->Info->FileInfos; /* Do a binary search */ int Lo = 0; @@ -1251,7 +1360,7 @@ static void ProcessFileInfo (InputData* D) /* Postprocess file infos */ { /* Get a pointer to the file info collection */ - Collection* FileInfos = &D->Info->FileInfo; + Collection* FileInfos = &D->Info->FileInfos; /* First, sort the file infos, so we can check for duplicates and do * binary search. @@ -1262,7 +1371,7 @@ static void ProcessFileInfo (InputData* D) if (CollCount (FileInfos) > 0) { /* Walk through the file infos and check for duplicates. If we find - * some, remove all but the first, so the file infos are unique after + * some, warn and remove them, so the file infos are unique after * that step. */ FileInfo* F = CollAt (FileInfos, 0); @@ -1294,12 +1403,13 @@ static void ProcessFileInfo (InputData* D) static void ProcessLineInfo (InputData* D) /* Postprocess line infos */ { - /* Get a pointer to the line info collection */ - Collection* LineInfos = &D->Info->LineInfo; + /* Get pointers to the collections */ + Collection* LineInfos = &D->LineInfos; + Collection* FileInfos = &D->Info->FileInfos; /* Walk over the line infos and replace the name by a pointer to the * corresponding file info struct. The LineInfo structs will get shrinked - * in this process. + * in this process. Add the line info to each file where it is defined. */ unsigned I = 0; while (I < CollCount (LineInfos)) { @@ -1326,11 +1436,83 @@ static void ProcessLineInfo (InputData* D) /* Shrink the line info struct effectively removing the file name * but set the pointer to the file info now. */ - CollReplace (LineInfos, PreenLineInfo (L, F), I); + L = PreenLineInfo (L, F); + CollReplace (LineInfos, L, I); + + /* Add this line info to the file where it is defined */ + CollAppend (&F->LineInfos, L); /* Next one */ ++I; } + + /* Walk over all files and sort the line infos for each file by ascending + * start address of the range, so we can do a binary search later. + */ + for (I = 0; I < CollCount (FileInfos); ++I) { + + /* Get a pointer to this file info */ + FileInfo* F = CollAt (FileInfos, I); + + /* Sort the line infos for this file */ + CollSort (&F->LineInfos, CompareLineInfo); + + /* If there are line info entries, place the first and last address + * of into the FileInfo struct itself, so we can rule out a FileInfo + * quickly when mapping an address to a line info. + */ + if (CollCount (&F->LineInfos) > 0) { + F->Start = ((const LineInfo*) CollFirst (&F->LineInfos))->Start; + F->End = ((const LineInfo*) CollLast (&F->LineInfos))->End; + } + + } +} + + + +static LineInfo* FindLineInfo (FileInfo* F, cc65_addr Addr) +/* Find the LineInfo for a given address */ +{ + Collection* LineInfos; + int Hi; + int Lo; + + + /* Each file info contains the first and last address for which line + * info is available, so we can rule out non matching ones quickly. + */ + if (Addr < F->Start || Addr > F->End) { + return 0; + } + + /* Get a pointer to the line info collection for this file */ + LineInfos = &F->LineInfos; + + /* Do a binary search */ + Lo = 0; + Hi = (int) CollCount (LineInfos) - 1; + while (Lo <= Hi) { + + /* Mid of range */ + int Cur = (Lo + Hi) / 2; + + /* Get item */ + LineInfo* CurItem = CollAt (LineInfos, Cur); + + /* Found? */ + if (Addr < CurItem->Start) { + Hi = Cur - 1; + } else if (Addr > CurItem->End) { + Lo = Cur + 1; + } else { + /* Found! */ + return CurItem; + } + } + + /* Not found */ + return 0; } @@ -1363,6 +1545,9 @@ cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc) 0, /* Integer constant */ STRBUF_INITIALIZER, /* String constant */ errorfunc, /* Function called in case of errors */ + 0, /* Major version number */ + 0, /* Minor version number */ + COLLECTION_INITIALIZER, /* Line information */ 0, /* Pointer to debug info */ }; @@ -1432,7 +1617,12 @@ cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc) * return NULL */ if (D.Errors > 0) { - /* Free the allocated debug info */ + /* Free allocated stuff */ + unsigned I; + for (I = 0; I < CollCount (&D.LineInfos); ++I) { + FreeLineInfo (CollAt (&D.LineInfos, I)); + } + DoneCollection (&D.LineInfos); FreeDbgInfo (D.Info); return 0; } @@ -1441,39 +1631,90 @@ cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc) ProcessFileInfo (&D); ProcessLineInfo (&D); + /* Free the collection that contained the line info */ + DoneCollection (&D.LineInfos); + /* Return the debug info struct that was created */ return D.Info; } -cc65_lineinfo* cc65_get_lineinfo (cc65_dbginfo handle, unsigned long addr) -/* Return line information for the given address */ +void cc65_free_dbginfo (cc65_dbginfo Handle) +/* Free debug information read from a file */ { - /* The passed handle is actually a pointer to a DbgInfo struct */ - DbgInfo* Info = handle; - assert (Info != 0); - - + if (Handle) { + FreeDbgInfo (Handle); + } } -void cc65_free_lineinfo (cc65_dbginfo handle, cc65_lineinfo* info) -/* Free line info returned by cc65_get_lineinfo() */ +cc65_lineinfo* cc65_get_lineinfo (cc65_dbginfo Handle, unsigned long Addr) +/* Return line information for the given address. The function returns 0 + * if no line information was found. + */ { - /* The passed handle is actually a pointer to a DbgInfo struct */ - DbgInfo* Info = handle; - assert (Info != 0); - -} + unsigned I; + Collection* FileInfos; + cc65_lineinfo* D = 0; + + /* We will place a list of line infos in a collection */ + Collection LineInfos = COLLECTION_INITIALIZER; + + /* Check the parameter */ + assert (Handle != 0); + + /* Walk over all files and search for matching line infos */ + FileInfos = &((DbgInfo*) Handle)->FileInfos; + for (I = 0; I < CollCount (FileInfos); ++I) { + /* Check if the file contains line info for this address */ + LineInfo* L = FindLineInfo (CollAt (FileInfos, I), Addr); + if (L != 0) { + CollAppend (&LineInfos, L); + } + } + /* Do we have line infos? */ + if (CollCount (&LineInfos) > 0) { + + /* Prepare the struct we will return to the caller */ + D = xmalloc (sizeof (*D) + + (CollCount (&LineInfos) - 1) * sizeof (D->data[0])); + D->count = CollCount (&LineInfos); + for (I = 0; I < D->count; ++I) { + + /* Pointer to this info */ + LineInfo* L = CollAt (&LineInfos, I); + + /* Copy data */ + D->data[I].name = L->FileInfo->FileName; + D->data[I].size = L->FileInfo->Size; + D->data[I].mtime = L->FileInfo->MTime; + D->data[I].line = L->Line; + D->data[I].start = L->Start; + D->data[I].end = L->End; + } + } + /* Free the line info collection */ + DoneCollection (&LineInfos); + /* Return the struct we've created */ + return D; +} +void cc65_free_lineinfo (cc65_dbginfo Handle, cc65_lineinfo* Info) +/* Free line info returned by cc65_get_lineinfo() */ +{ + /* Just for completeness, check the handle */ + assert (Handle != 0); + /* Just free the memory */ + xfree (Info); +} diff --git a/src/dbginfo/dbginfo.h b/src/dbginfo/dbginfo.h index 1f7f60349..80a51cf13 100644 --- a/src/dbginfo/dbginfo.h +++ b/src/dbginfo/dbginfo.h @@ -39,22 +39,35 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ +/* Data types used for addresses and line numbers. Change to "unsigned long" + * if you ever want to run the code on a 16-bit machine. + */ +typedef unsigned cc65_line; /* Used to store line numbers */ +typedef unsigned cc65_addr; /* Use to store (65xx) addresses */ + /* Pointer to an opaque data structure containing information from the debug * info file. Actually a handle to the data in the file. */ typedef void* cc65_dbginfo; +/* ### Parseerror */ +typedef enum cc65_error_severity cc65_error_severity; +enum cc65_error_severity { + CC65_WARNING, + CC65_ERROR, +}; + /* Warnings/errors in cc65_read_dbginfo are passed via this struct */ typedef struct cc65_parseerror cc65_parseerror; struct cc65_parseerror { - unsigned type; /* 0 = warning, 1 = error */ + cc65_error_severity type; /* Type of error */ const char* name; /* Name of input file */ - unsigned long line; /* Error line */ + cc65_line line; /* Error line */ unsigned column; /* Error column */ char errormsg[1]; /* Error message */ }; @@ -62,21 +75,17 @@ struct cc65_parseerror { /* Function that is called in case of parse errors */ typedef void (*cc65_errorfunc) (const struct cc65_parseerror*); -/* File information */ -typedef struct cc65_fileinfo cc65_fileinfo; -struct cc65_fileinfo { - char* name; /* Name of file with full path */ - unsigned long size; /* Size of file */ - unsigned long mtime; /* Modification time */ -}; - /* Line information */ typedef struct cc65_lineinfo cc65_lineinfo; struct cc65_lineinfo { unsigned count; /* Count of data sets that follow */ struct { - cc65_fileinfo* fileinfo; /* File information including name */ - unsigned long line; /* Line number */ + const char* name; /* Name of the file */ + unsigned long size; /* Size of file */ + unsigned long mtime; /* Modification time */ + cc65_line line; /* Line number */ + cc65_addr start; /* Start address for this line */ + cc65_addr end; /* End address for this line */ } data[1]; }; @@ -96,8 +105,13 @@ cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc); * read successfully, NULL is returned. */ +void cc65_free_dbginfo (cc65_dbginfo Handle); +/* Free debug information read from a file */ + cc65_lineinfo* cc65_get_lineinfo (cc65_dbginfo handle, unsigned long addr); -/* Return line information for the given address */ +/* Return line information for the given address. The function returns NULL + * if no line information was found. + */ void cc65_free_lineinfo (cc65_dbginfo handle, cc65_lineinfo* info); /* Free line info returned by cc65_get_lineinfo() */ diff --git a/src/dbginfo/dbgtest.c b/src/dbginfo/dbgtest.c index ac4e52c50..73000a1b4 100644 --- a/src/dbginfo/dbgtest.c +++ b/src/dbginfo/dbgtest.c @@ -46,7 +46,7 @@ static void ErrorFunc (const struct cc65_parseerror* E) "%s:%s(%lu): %s\n", E->type? "Error" : "Warning", E->name, - E->line, + (unsigned long) E->line, E->errormsg); } @@ -63,8 +63,9 @@ static void Usage (void) int main (int argc, char** argv) { - const char* Input; - cc65_dbginfo Handle; + const char* Input; + cc65_dbginfo Info; + unsigned long Addr; /* Input file is argument */ @@ -73,11 +74,37 @@ int main (int argc, char** argv) } Input = argv[1]; - - Handle = cc65_read_dbginfo (Input, ErrorFunc); - if (Handle == 0) { - fprintf (stderr, "No handle\n"); + /* Read the file */ + Info = cc65_read_dbginfo (Input, ErrorFunc); + if (Info == 0) { + fprintf (stderr, "Error reading input file - aborting\n"); + return 1; + } + printf ("Input file \"%s\" successfully read\n", Input); + + /* Output debug information for all addresses in the complete 6502 address + * space. This is also sort of a benchmark for the search algorithms. + */ + for (Addr = 0; Addr < 0x10000; ++Addr) { + cc65_lineinfo* L = cc65_get_lineinfo (Info, Addr); + if (L) { + unsigned I; + printf ("$%04lX: ", Addr); + for (I = 0; I < L->count; ++I) { + if (I > 0) { + printf (", "); + } + printf ("%s(%lu)", L->data[I].name, + (unsigned long) L->data[I].line); + } + printf ("\n"); + cc65_free_lineinfo (Info, L); + } } + + /* Free the debug info */ + cc65_free_dbginfo (Info); + return 0; } diff --git a/src/dbginfo/make/gcc.mak b/src/dbginfo/make/gcc.mak index 06618cf06..750792d68 100644 --- a/src/dbginfo/make/gcc.mak +++ b/src/dbginfo/make/gcc.mak @@ -12,9 +12,9 @@ EXE = dbgtest # CC = gcc -CFLAGS = -O2 -g -Wall -W +CFLAGS = -g -O2 -Wall -W EBIND = emxbind -LDFLAGS = +LDFLAGS = -g # ------------------------------------------------------------------------------ # Object files and libraries to link -- 2.39.5