Collection SegInfoById; /* Segment infos sorted by id */
Collection FileInfoByName; /* File infos sorted by name */
Collection FileInfoById; /* File infos sorted by id */
- Collection LineInfoByAddr; /* Line information sorted by address */
- Collection SymInfoByName; /* Symbol information sorted by name */
+ Collection LineInfoByAddr; /* Line infos sorted by address */
+ Collection SymInfoByName; /* Symbol infos sorted by name */
+ Collection SymInfoByVal; /* Symbol infos sorted by value */
};
/* Input tokens */
static int CompareSymInfoByName (const void* L, const void* R)
/* Helper function to sort symbol infos in a collection by name */
{
- /* Sort by file name */
+ /* Sort by symbol name */
return strcmp (((const SymInfo*) L)->SymName,
((const SymInfo*) R)->SymName);
}
+static int CompareSymInfoByVal (const void* L, const void* R)
+/* Helper function to sort symbol infos in a collection by value */
+{
+ /* Sort by symbol value. If both are equal, sort by symbol name so it
+ * looks nice when such a list is returned.
+ */
+ if (((const SymInfo*) L)->Value > ((const SymInfo*) R)->Value) {
+ return 1;
+ } else if (((const SymInfo*) L)->Value < ((const SymInfo*) R)->Value) {
+ return -1;
+ } else {
+ return CompareSymInfoByName (L, R);
+ }
+}
+
+
+
/*****************************************************************************/
/* Debug info */
/*****************************************************************************/
InitCollection (&Info->FileInfoById);
InitCollection (&Info->LineInfoByAddr);
InitCollection (&Info->SymInfoByName);
+ InitCollection (&Info->SymInfoByVal);
/* Return it */
return Info;
FreeSymInfo (CollAt (&Info->SymInfoByName, I));
}
DoneCollection (&Info->SymInfoByName);
+ DoneCollection (&Info->SymInfoByVal);
/* Free the structure itself */
xfree (Info);
+static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
+/* Copy data from a SymInfo struct to the cc65_symboldata struct returned to
+ * the caller.
+ */
+{
+ D->symbol_name = S->SymName;
+ D->symbol_type = S->Type;
+ D->symbol_value = S->Value;
+}
+
+
+
static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...)
/* Call the user supplied parse error function */
{
/* Create the symbol info and remember it */
S = NewSymInfo (&SymName, Value, Type);
CollAppend (&D->Info->SymInfoByName, S);
+ CollAppend (&D->Info->SymInfoByVal, S);
ErrorExit:
/* Entry point in case of errors */
{
/* Get pointers to the symbol info collections */
Collection* SymInfoByName = &D->Info->SymInfoByName;
+ Collection* SymInfoByVal = &D->Info->SymInfoByVal;
- /* Sort the symbol infos by name */
+ /* Sort the symbol infos */
CollSort (SymInfoByName, CompareSymInfoByName);
+ CollSort (SymInfoByVal, CompareSymInfoByVal);
}
+static int FindSymInfoByValue (Collection* SymInfos, long Value, int* Index)
+/* Find the SymInfo for a given value. The function returns true if the
+ * value was found. In this case, Index contains the index of the first item
+ * that matches. If the item wasn't found, the function returns false and
+ * Index contains the insert position for the given value.
+ */
+{
+ /* Do a binary search */
+ int Lo = 0;
+ int Hi = (int) CollCount (SymInfos) - 1;
+ int Found = 0;
+ while (Lo <= Hi) {
+
+ /* Mid of range */
+ int Cur = (Lo + Hi) / 2;
+
+ /* Get item */
+ SymInfo* CurItem = CollAt (SymInfos, Cur);
+
+ /* Found? */
+ if (Value > CurItem->Value) {
+ Lo = Cur + 1;
+ } else {
+ Hi = Cur - 1;
+ /* Since we may have duplicates, repeat the search until we've
+ * the first item that has a match.
+ */
+ if (Value == CurItem->Value) {
+ Found = 1;
+ }
+ }
+ }
+
+ /* Pass back the index. This is also the insert position */
+ *Index = Lo;
+ return Found;
+}
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
/* Fill in the data */
D->count = Count;
- while (Count--) {
+ for (I = 0; I < Count; ++I) {
+ /* Copy the data */
+ CopySymInfo (D->data + I, CollAt (SymInfoByName, Index++));
+ }
- /* Get this item */
- const SymInfo* S = CollAt (SymInfoByName, Index);
+ /* Return the result */
+ return D;
+}
+
+
+
+cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start, cc65_addr End)
+/* Return a list of labels in the given range. End is inclusive. The function
+ * return NULL if no symbols withing the given range are found. Non label
+ * symbols are ignored and not returned.
+ */
+{
+ DbgInfo* Info;
+ Collection* SymInfoByVal;
+ Collection SymInfoList = COLLECTION_INITIALIZER;
+ cc65_symbolinfo* D;
+ unsigned I;
+ int Index;
+
+ /* Check the parameter */
+ assert (Handle != 0);
+
+ /* The handle is actually a pointer to a debug info struct */
+ Info = (DbgInfo*) Handle;
+ /* Get a pointer to the symbol list */
+ SymInfoByVal = &Info->SymInfoByVal;
+
+ /* Search for the symbol. Because we're searching for a range, we cannot
+ * make use of the function result.
+ */
+ FindSymInfoByValue (SymInfoByVal, Start, &Index);
+
+ /* Start from the given index, check all symbols until the end address is
+ * reached. Place all symbols into SymInfoList for later.
+ */
+ for (I = Index; I < CollCount (SymInfoByVal); ++I) {
+
+ /* Get the item */
+ SymInfo* Item = CollAt (SymInfoByVal, I);
+
+ /* The collection is sorted by address, so if we get a value larger
+ * than the end address, we're done.
+ */
+ if (Item->Value > (long) End) {
+ break;
+ }
+
+ /* Ignore non-labels */
+ if (Item->Type != CC65_SYM_LABEL) {
+ continue;
+ }
+
+ /* Ok, remember this one */
+ CollAppend (&SymInfoList, Item);
+ }
+
+ /* If we don't have any labels within the range, bail out. No memory has
+ * been allocated for SymInfoList.
+ */
+ if (CollCount (&SymInfoList) == 0) {
+ return 0;
+ }
+
+ /* Allocate memory for the data structure returned to the caller */
+ D = xmalloc (sizeof (*D) + (CollCount (&SymInfoList)- 1) * sizeof (D->data[0]));
+
+ /* Fill in the data */
+ D->count = CollCount (&SymInfoList);
+ for (I = 0; I < CollCount (&SymInfoList); ++I) {
/* Copy the data */
- D->data[I].symbol_name = S->SymName;
- D->data[I].symbol_type = S->Type;
- D->data[I].symbol_value = S->Value;
+ CopySymInfo (D->data + I, CollAt (&SymInfoList, I));
}
+ /* Free the collection */
+ DoneCollection (&SymInfoList);
+
/* Return the result */
return D;
}
+static void PrintSourceData (const cc65_sourcedata* D)
+/* Print the data for one source file */
+{
+ printf (" %s\n", D->source_name);
+}
+
+
+
+static void PrintSegmentData (const cc65_segmentdata* D)
+/* Print the data for one segment */
+{
+ printf (" %-20s $%06lX $%04lX",
+ D->segment_name,
+ (unsigned long) D->segment_start,
+ (unsigned long) D->segment_size);
+ if (D->output_name) {
+ printf (" %-20s $%06lX", D->output_name, D->output_offs);
+ }
+ putchar ('\n');
+}
+
+
+
+static void PrintLineData (const cc65_linedata* D)
+/* Print the data for one source line */
+{
+ printf (" %s(%lu)", D->source_name, (unsigned long) D->source_line);
+ if (D->output_name) {
+ printf (" [%s($%06lX)]", D->output_name, D->output_offs);
+ }
+ putchar ('\n');
+}
+
+
+
+static void PrintSymbolData (const cc65_symboldata* D)
+/* Print the data for one symbol */
+{
+ printf (" %-20s = %04lX\n", D->symbol_name, D->symbol_value);
+}
+
+
+
+static void PrintSourceInfo (cc65_sourceinfo* Sources)
+/* Output the list of source files */
+{
+ unsigned I;
+ if (Sources) {
+ for (I = 0; I < Sources->count; ++I) {
+ PrintSourceData (Sources->data + I);
+ }
+ }
+}
+
+
+
+static void PrintSegmentInfo (cc65_segmentinfo* Segments)
+/* Output the list of segments */
+{
+ unsigned I;
+ if (Segments) {
+ for (I = 0; I < Segments->count; ++I) {
+ PrintSegmentData (Segments->data + I);
+ }
+ }
+}
+
+
+
+static void PrintLineInfo (const cc65_lineinfo* Info)
+/* Print a list of line infos */
+{
+ unsigned I;
+ if (Info) {
+ for (I = 0; I < Info->count; ++I) {
+ PrintLineData (Info->data + I);
+ }
+ }
+}
+
+
+
+static void PrintSymbolInfo (const cc65_symbolinfo* Symbols)
+/* Print a list of symbol infos */
+{
+ unsigned I;
+ if (Symbols) {
+ for (I = 0; I < Symbols->count; ++I) {
+ PrintSymbolData (Symbols->data + I);
+ }
+ }
+}
+
+
+
int main (int argc, char** argv)
{
const char* Input;
cc65_segmentinfo* Segments;
cc65_lineinfo* Lines;
cc65_symbolinfo* Symbols;
- unsigned I;
- unsigned long Addr;
+ cc65_addr Addr;
/* Input file is argument */
/* Output a list of files */
printf ("List of source files:\n");
Sources = cc65_get_sourcelist (Info);
- for (I = 0; I < Sources->count; ++I) {
- printf (" %s\n", Sources->data[I].source_name);
- }
+ PrintSourceInfo (Sources);
cc65_free_sourceinfo (Info, Sources);
/* Output a list of segments */
printf ("Segments processed when linking:\n");
Segments = cc65_get_segmentlist (Info);
- for (I = 0; I < Segments->count; ++I) {
- printf (" %-20s $%06lX $%04lX",
- Segments->data[I].segment_name,
- (unsigned long) Segments->data[I].segment_start,
- (unsigned long) Segments->data[I].segment_size);
- if (Segments->data[I].output_name) {
- printf (" %-20s $%06lX",
- Segments->data[I].output_name,
- Segments->data[I].output_offs);
- }
- putchar ('\n');
- }
+ PrintSegmentInfo (Segments);
cc65_free_segmentinfo (Info, Segments);
/* Check one line */
if (Lines == 0) {
printf (" Not found\n");
} else {
- printf (" Code range is $%04X-$%04X\n",
- Lines->data[0].line_start,
- Lines->data[0].line_end);
+ PrintLineInfo (Lines);
cc65_free_lineinfo (Info, Lines);
}
for (Addr = 0; Addr < 0x10000; ++Addr) {
Lines = cc65_lineinfo_byaddr (Info, Addr);
if (Lines) {
- unsigned I;
- printf (" $%04lX: ", Addr);
- for (I = 0; I < Lines->count; ++I) {
- if (I > 0) {
- printf (", ");
- }
- printf ("%s(%lu)",
- Lines->data[I].source_name,
- (unsigned long) Lines->data[I].source_line);
- if (Lines->data[I].output_name) {
- printf (" %s($%06lX)",
- Lines->data[I].output_name,
- Lines->data[I].output_offs);
-
- }
- }
- printf ("\n");
+ printf (" $%04lX:\n", (unsigned long) Addr);
+ PrintLineInfo (Lines);
cc65_free_lineinfo (Info, Lines);
}
}
Symbols = cc65_symbol_byname (Info, "_main");
if (Symbols == 0) {
printf (" Not found\n");
- } else {
- unsigned I;
- for (I = 0; I < Symbols->count; ++I) {
- printf (" %-20s = %04lX\n",
- Symbols->data[I].symbol_name,
- Symbols->data[I].symbol_value);
- }
+ Addr = 0x800;
+ } else {
+ PrintSymbolInfo (Symbols);
+ Addr = Symbols->data[0].symbol_value;
cc65_free_symbolinfo (Info, Symbols);
}
+ /* Print symbols for the next $100 bytes starting from main (or 0x800) */
+ printf ("Requesting labels for $%04lX-$%04lX:\n",
+ (unsigned long) Addr, (unsigned long) Addr + 0xFF);
+ Symbols = cc65_symbol_inrange (Info, Addr, Addr + 0xFF);
+ if (Symbols == 0) {
+ printf (" None found\n");
+ } else {
+ PrintSymbolInfo (Symbols);
+ cc65_free_symbolinfo (Info, Symbols);
+ }
/* Free the debug info */
cc65_free_dbginfo (Info);