Fixed a problem: Removing duplicate file entries (entries with the same name)

isn't allowed, since these entries may be referenced. Since we must be able to
handle duplicate names anyway (they may be old/new versions of one file), we
can also have duplicates in general. Cleanup the list using time stamps and
sizes before returning it to the caller.


git-svn-id: svn://svn.cc65.org/cc65/trunk@5044 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2011-06-08 20:53:29 +00:00
parent c65292b78d
commit 7c926ada70

View File

@@ -287,6 +287,58 @@ static void xfree (void* Block)
static cc65_lineinfo* new_cc65_lineinfo (unsigned Count)
/* Allocate and return a cc65_lineinfo struct that is able to hold Count
* entries. Initialize the count field of the returned struct.
*/
{
cc65_lineinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) +
Count * sizeof (L->data[0]));
L->count = Count;
return L;
}
static cc65_sourceinfo* new_cc65_sourceinfo (unsigned Count)
/* Allocate and return a cc65_sourceinfo struct that is able to hold Count
* entries. Initialize the count field of the returned struct.
*/
{
cc65_sourceinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
S->count = Count;
return S;
}
static cc65_segmentinfo* new_cc65_segmentinfo (unsigned Count)
/* Allocate and return a cc65_segmentinfo struct that is able to hold Count
* entries. Initialize the count field of the returned struct.
*/
{
cc65_segmentinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
S->count = Count;
return S;
}
static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count)
/* Allocate and return a cc65_symbolinfo struct that is able to hold Count
* entries. Initialize the count field of the returned struct.
*/
{
cc65_symbolinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) +
Count * sizeof (S->data[0]));
S->count = Count;
return S;
}
/*****************************************************************************/ /*****************************************************************************/
/* Dynamic strings */ /* Dynamic strings */
/*****************************************************************************/ /*****************************************************************************/
@@ -938,9 +990,27 @@ static void FreeFileInfo (FileInfo* F)
static int CompareFileInfoByName (const void* L, const void* R) static int CompareFileInfoByName (const void* L, const void* R)
/* Helper function to sort file infos in a collection by name */ /* Helper function to sort file infos in a collection by name */
{ {
/* Sort by file name */ /* Sort by file name. If names are equal, sort by timestamp,
return strcmp (((const FileInfo*) L)->FileName, * then sort by size. Which means, identical files will go
((const FileInfo*) R)->FileName); * together.
*/
int Res = strcmp (((const FileInfo*) L)->FileName,
((const FileInfo*) R)->FileName);
if (Res != 0) {
return Res;
}
if (((const FileInfo*) L)->MTime > ((const FileInfo*) R)->MTime) {
return 1;
} else if (((const FileInfo*) L)->MTime < ((const FileInfo*) R)->MTime) {
return -1;
}
if (((const FileInfo*) L)->Size > ((const FileInfo*) R)->Size) {
return 1;
} else if (((const FileInfo*) L)->Size < ((const FileInfo*) R)->Size) {
return -1;
} else {
return 0;
}
} }
@@ -1477,7 +1547,7 @@ static void NextToken (InputData* D)
/* Skip whitespace */ /* Skip whitespace */
while (D->C == ' ' || D->C == '\t') { while (D->C == ' ' || D->C == '\t' || D->C == '\r') {
NextChar (D); NextChar (D);
} }
@@ -2371,12 +2441,18 @@ static SegInfo* FindSegInfoById (InputData* D, unsigned Id)
static FileInfo* FindFileInfoByName (Collection* FileInfos, const char* FileName) static int FindFileInfoByName (Collection* FileInfos, const char* FileName,
/* Find the FileInfo for a given file name */ unsigned* Index)
/* Find the FileInfo for a given file name. The function returns true if the
* name 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 FileName.
*/
{ {
/* Do a binary search */ /* Do a binary search */
int Lo = 0; int Lo = 0;
int Hi = (int) CollCount (FileInfos) - 1; int Hi = (int) CollCount (FileInfos) - 1;
int Found = 0;
while (Lo <= Hi) { while (Lo <= Hi) {
/* Mid of range */ /* Mid of range */
@@ -2391,16 +2467,20 @@ static FileInfo* FindFileInfoByName (Collection* FileInfos, const char* FileName
/* Found? */ /* Found? */
if (Res < 0) { if (Res < 0) {
Lo = Cur + 1; Lo = Cur + 1;
} else if (Res > 0) {
Hi = Cur - 1;
} else { } else {
/* Found! */ Hi = Cur - 1;
return CurItem; /* Since we may have duplicates, repeat the search until we've
* the first item that has a match.
*/
if (Res == 0) {
Found = 1;
}
} }
} }
/* Not found */ /* Pass back the index. This is also the insert position */
return 0; *Index = Lo;
return Found;
} }
@@ -2462,52 +2542,22 @@ static void ProcessSegInfo (InputData* D)
static void ProcessFileInfo (InputData* D) static void ProcessFileInfo (InputData* D)
/* Postprocess file infos */ /* Postprocess file infos */
{ {
unsigned I;
/* Get pointers to the file info collections */ /* Get pointers to the file info collections */
Collection* FileInfoByName = &D->Info->FileInfoByName; Collection* FileInfoByName = &D->Info->FileInfoByName;
Collection* FileInfoById = &D->Info->FileInfoById; Collection* FileInfoById = &D->Info->FileInfoById;
/* First, sort the file infos, so we can check for duplicates and do /* First, sort the file infos, so we can do a binary search */
* binary search.
*/
CollSort (FileInfoByName, CompareFileInfoByName); CollSort (FileInfoByName, CompareFileInfoByName);
/* Cannot work on an empty collection */ /* Copy the file infos to another collection that will be sorted by id */
if (CollCount (FileInfoByName) > 0) { for (I = 0; I < CollCount (FileInfoByName); ++I) {
CollAppend (FileInfoById, CollAt (FileInfoByName, I));
/* Walk through the file infos sorted by name and check for duplicates.
* If we find some, warn and remove them, so the file infos are unique
* after that step.
*/
FileInfo* F = CollAt (FileInfoByName, 0);
unsigned I = 1;
while (I < CollCount (FileInfoByName)) {
FileInfo* Next = CollAt (FileInfoByName, I);
if (strcmp (F->FileName, Next->FileName) == 0) {
/* Warn only if time stamp and/or size is different */
if (F->Size != Next->Size || F->MTime != Next->MTime) {
ParseError (D,
CC65_WARNING,
"Duplicate file entry for \"%s\"",
F->FileName);
}
/* Remove the duplicate entry */
FreeFileInfo (Next);
CollDelete (FileInfoByName, I);
} else {
/* This one is ok, check the next entry */
F = Next;
++I;
}
}
/* 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, CompareFileInfoById);
} }
/* Sort this collection */
CollSort (FileInfoById, CompareFileInfoById);
} }
@@ -2703,7 +2753,7 @@ static void ProcessSymInfo (InputData* D)
static int FindSymInfoByName (Collection* SymInfos, const char* SymName, int* Index) static int FindSymInfoByName (Collection* SymInfos, const char* SymName, unsigned* Index)
/* Find the SymInfo for a given file name. The function returns true if the /* Find the SymInfo for a given file name. The function returns true if the
* name was found. In this case, Index contains the index of the first item * name 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 * that matches. If the item wasn't found, the function returns false and
@@ -2746,7 +2796,7 @@ static int FindSymInfoByName (Collection* SymInfos, const char* SymName, int* In
static int FindSymInfoByValue (Collection* SymInfos, long Value, int* Index) static int FindSymInfoByValue (Collection* SymInfos, long Value, unsigned* Index)
/* Find the SymInfo for a given value. The function returns true if the /* 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 * 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 * that matches. If the item wasn't found, the function returns false and
@@ -2822,7 +2872,7 @@ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc)
D.Error = ErrFunc; D.Error = ErrFunc;
/* Open the input file */ /* Open the input file */
D.F = fopen (D.FileName, "r"); D.F = fopen (D.FileName, "rt");
if (D.F == 0) { if (D.F == 0) {
/* Cannot open */ /* Cannot open */
ParseError (&D, CC65_ERROR, ParseError (&D, CC65_ERROR,
@@ -2966,8 +3016,7 @@ cc65_lineinfo* cc65_lineinfo_byaddr (cc65_dbginfo Handle, unsigned long Addr)
unsigned I; unsigned I;
/* Prepare the struct we will return to the caller */ /* Prepare the struct we will return to the caller */
D = xmalloc (sizeof (*D) + (E->Count - 1) * sizeof (D->data[0])); D = new_cc65_lineinfo (E->Count);
D->count = E->Count;
if (E->Count == 1) { if (E->Count == 1) {
CopyLineInfo (D->data, E->Data); CopyLineInfo (D->data, E->Data);
} else { } else {
@@ -2992,8 +3041,10 @@ cc65_lineinfo* cc65_lineinfo_byname (cc65_dbginfo Handle, const char* FileName,
{ {
DbgInfo* Info; DbgInfo* Info;
FileInfo* F; FileInfo* F;
LineInfo* L;
cc65_lineinfo* D; cc65_lineinfo* D;
int Found;
unsigned Index;
Collection LineInfoList = COLLECTION_INITIALIZER;
/* Check the parameter */ /* Check the parameter */
assert (Handle != 0); assert (Handle != 0);
@@ -3001,26 +3052,53 @@ cc65_lineinfo* cc65_lineinfo_byname (cc65_dbginfo Handle, const char* FileName,
/* The handle is actually a pointer to a debug info struct */ /* The handle is actually a pointer to a debug info struct */
Info = (DbgInfo*) Handle; Info = (DbgInfo*) Handle;
/* Get the file info */ /* Search for the first file with this name */
F = FindFileInfoByName (&Info->FileInfoByName, FileName); Found = FindFileInfoByName (&Info->FileInfoByName, FileName, &Index);
if (F == 0) { if (!Found) {
/* File not found */
return 0; return 0;
} }
/* Search in the file for the given line */ /* Loop over all files with this name */
L = FindLineInfoByLine (F, Line); F = CollAt (&Info->FileInfoByName, Index);
if (L == 0) { while (Found) {
/* Line not found */
/* Search in the file for the given line */
LineInfo* L = FindLineInfoByLine (F, Line);
if (L) {
/* Remember the line info */
CollAppend (&LineInfoList, L);
}
/* Next entry */
++Index;
/* If the index is valid, check if the next entry is a file with the
* same name.
*/
if (Index < CollCount (&Info->FileInfoByName)) {
F = CollAt (&Info->FileInfoByName, Index);
Found = (strcmp (F->FileName, FileName) == 0);
} else {
Found = 0;
}
}
/* Check if we have entries */
if (CollCount (&LineInfoList) == 0) {
/* Nope */
return 0; return 0;
} }
/* Prepare the struct we will return to the caller */ /* Prepare the struct we will return to the caller */
D = xmalloc (sizeof (*D)); D = new_cc65_lineinfo (CollCount (&LineInfoList));
D->count = 1;
/* Copy data */ /* Copy the data */
CopyLineInfo (D->data, L); for (Index = 0; Index < CollCount (&LineInfoList); ++Index) {
CopyLineInfo (D->data + Index, CollAt (&LineInfoList, Index));
}
/* Delete the temporary data collection */
DoneCollection (&LineInfoList);
/* Return the allocated struct */ /* Return the allocated struct */
return D; return D;
@@ -3057,21 +3135,34 @@ cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle)
/* Get a pointer to the file list */ /* Get a pointer to the file list */
FileInfoByName = &Info->FileInfoByName; FileInfoByName = &Info->FileInfoByName;
/* Allocate memory for the data structure returned to the caller */ /* Allocate memory for the data structure returned to the caller.
D = xmalloc (sizeof (*D) - sizeof (D->data[0]) + * Note: To simplify things, we will allocate the maximum amount of
CollCount (FileInfoByName) * sizeof (D->data[0])); * memory, we may need later. This saves us the overhead of walking
* the list twice.
*/
D = new_cc65_sourceinfo (CollCount (FileInfoByName));
/* Fill in the data */ /* Fill in the data, skipping duplicate entries */
D->count = CollCount (FileInfoByName); D->count = 0;
for (I = 0; I < CollCount (FileInfoByName); ++I) { for (I = 0; I < CollCount (FileInfoByName); ++I) {
/* Get this item */ /* Get this item */
const FileInfo* F = CollAt (FileInfoByName, I); const FileInfo* F = CollAt (FileInfoByName, I);
/* If this is not the first entry, compare it to the last one and
* don't add it if it is identical.
*/
if (I > 0 && CompareFileInfoByName (F, CollAt (FileInfoByName, I-1)) == 0) {
continue;
}
/* Copy the data */ /* Copy the data */
D->data[I].source_name = F->FileName; D->data[D->count].source_name = F->FileName;
D->data[I].source_size = F->Size; D->data[D->count].source_size = F->Size;
D->data[I].source_mtime = F->MTime; D->data[D->count].source_mtime = F->MTime;
/* One more valid entry */
++D->count;
} }
/* Return the result */ /* Return the result */
@@ -3110,8 +3201,7 @@ cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle)
SegInfoByName = &Info->SegInfoByName; SegInfoByName = &Info->SegInfoByName;
/* Allocate memory for the data structure returned to the caller */ /* Allocate memory for the data structure returned to the caller */
D = xmalloc (sizeof (*D) - sizeof (D->data[0]) + D = new_cc65_segmentinfo (CollCount (SegInfoByName));
CollCount (SegInfoByName) * sizeof (D->data[0]));
/* Fill in the data */ /* Fill in the data */
D->count = CollCount (SegInfoByName); D->count = CollCount (SegInfoByName);
@@ -3155,7 +3245,7 @@ cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
Collection* SymInfoByName; Collection* SymInfoByName;
cc65_symbolinfo* D; cc65_symbolinfo* D;
unsigned I; unsigned I;
int Index; unsigned Index;
unsigned Count; unsigned Count;
/* Check the parameter */ /* Check the parameter */
@@ -3186,7 +3276,7 @@ cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name)
} }
/* Allocate memory for the data structure returned to the caller */ /* Allocate memory for the data structure returned to the caller */
D = xmalloc (sizeof (*D) + (Count - 1) * sizeof (D->data[0])); D = new_cc65_symbolinfo (Count);
/* Fill in the data */ /* Fill in the data */
D->count = Count; D->count = Count;
@@ -3212,7 +3302,7 @@ cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start, cc65
Collection SymInfoList = COLLECTION_INITIALIZER; Collection SymInfoList = COLLECTION_INITIALIZER;
cc65_symbolinfo* D; cc65_symbolinfo* D;
unsigned I; unsigned I;
int Index; unsigned Index;
/* Check the parameter */ /* Check the parameter */
assert (Handle != 0); assert (Handle != 0);
@@ -3260,7 +3350,7 @@ cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start, cc65
} }
/* Allocate memory for the data structure returned to the caller */ /* Allocate memory for the data structure returned to the caller */
D = xmalloc (sizeof (*D) + (CollCount (&SymInfoList)- 1) * sizeof (D->data[0])); D = new_cc65_symbolinfo (CollCount (&SymInfoList));
/* Fill in the data */ /* Fill in the data */
D->count = CollCount (&SymInfoList); D->count = CollCount (&SymInfoList);