]> git.sur5r.net Git - cc65/blobdiff - src/ld65/fileinfo.c
Removed unneeded include files.
[cc65] / src / ld65 / fileinfo.c
index 7965d574f6c987a32faf4aab4a8a8317b3b449ba..6c17fbd4a23b8d722e72b990fe9713c347779f1f 100644 (file)
@@ -2,11 +2,11 @@
 /*                                                                           */
 /*                               fileinfo.c                                 */
 /*                                                                           */
-/*                       sOURCE FILE INFO STRUCTURE                         */
+/*                       Source file info structure                         */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2001-2010, Ullrich von Bassewitz                                      */
+/* (C) 2001-2011, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 
 
 /* common */
+#include "coll.h"
 #include "xmalloc.h"
 
 /* ld65 */
 #include "fileio.h"
 #include "fileinfo.h"
+#include "objdata.h"
+#include "spool.h"
+
+
+
+/*****************************************************************************/
+/*                                   Data                                    */
+/*****************************************************************************/
+
+
+
+/* A list of all file infos without duplicates */
+static Collection FileInfos = STATIC_COLLECTION_INITIALIZER;
 
 
 
 
 
 
-static FileInfo* NewFileInfo (void)
-/* Allocate and initialize a new FileInfo struct and return it */
+static int FindFileInfo (unsigned 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.
+ */
 {
-    /* We will assign file info ids in increasing order of creation */
-    static unsigned Id = 0;
+    /* Do a binary search */
+    int Lo = 0;
+    int Hi = (int) CollCount (&FileInfos) - 1;
+    int Found = 0;
+    while (Lo <= Hi) {
+
+        /* Mid of range */
+        int Cur = (Lo + Hi) / 2;
+
+        /* Get item */
+        FileInfo* CurItem = CollAt (&FileInfos, Cur);
+
+        /* Found? */
+        if (CurItem->Name < Name) {
+            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 (CurItem->Name == Name) {
+                Found = 1;
+            }
+        }
+    }
+
+    /* Pass back the index. This is also the insert position */
+    *Index = Lo;
+    return Found;
+}
+
 
+
+static FileInfo* NewFileInfo (unsigned Name, unsigned long MTime, unsigned long Size)
+/* Allocate and initialize a new FileInfo struct and return it */
+{
     /* Allocate memory */
     FileInfo* FI = xmalloc (sizeof (FileInfo));
 
     /* Initialize stuff */
-    FI->Id = Id++;
+    FI->Id      = ~0U;
+    FI->Name    = Name;
+    FI->MTime   = MTime;
+    FI->Size    = Size;
+    FI->Modules = EmptyCollection;
 
     /* Return the new struct */
     return FI;
@@ -66,16 +121,71 @@ static FileInfo* NewFileInfo (void)
 
 
 
+static void FreeFileInfo (FileInfo* FI)
+/* Free a file info structure */
+{
+    /* Free the collection */
+    DoneCollection (&FI->Modules);
+
+    /* Free memory for the structure */
+    xfree (FI);
+}
+
+
+
 FileInfo* ReadFileInfo (FILE* F, ObjData* O)
 /* Read a file info from a file and return it */
 {
-    /* Allocate a new FileInfo structure */
-    FileInfo* FI = NewFileInfo ();
+    FileInfo* FI;
 
     /* Read the fields from the file */
-    FI->Name  = MakeGlobalStringId (O, ReadVar (F));
-    FI->MTime = Read32 (F);
-    FI->Size  = Read32 (F);
+    unsigned      Name  = MakeGlobalStringId (O, ReadVar (F));
+    unsigned long MTime = Read32 (F);
+    unsigned long Size  = ReadVar (F);
+
+    /* Search for the first entry with this name */
+    unsigned Index;
+    if (FindFileInfo (Name, &Index)) {
+
+        /* We have at least one such entry. Try all of them and, if size and
+         * modification time matches, return the first match. When the loop
+         * is terminated without finding an entry, Index points one behind
+         * the last entry with the name, which is the perfect insert position.
+         */
+        FI = CollAt (&FileInfos, Index);
+        while (1) {
+
+            /* Check size and modification time stamp */
+            if (FI->Size == Size && FI->MTime == MTime) {
+                /* Remember that the modules uses this file info, then return it */
+                CollAppend (&FI->Modules, O);
+                return FI;
+            }
+
+            /* Check the next one */
+            if (++Index >= CollCount (&FileInfos)) {
+                /* Nothing left */
+                break;
+            }
+            FI = CollAt (&FileInfos, Index);
+
+            /* Done if the name differs */
+            if (FI->Name != Name) {
+                break;
+            }
+        }
+    }
+
+    /* Not found. Allocate a new FileInfo structure */
+    FI = NewFileInfo (Name, MTime, Size);
+
+    /* Remember that this module uses the file info */
+    CollAppend (&FI->Modules, O);
+
+    /* Insert the file info in our global list. Index points to the insert
+     * position.
+     */
+    CollInsert (&FileInfos, FI, Index);
 
     /* Return the new struct */
     return FI;
@@ -83,3 +193,74 @@ FileInfo* ReadFileInfo (FILE* F, ObjData* O)
 
 
 
+unsigned FileInfoCount (void)
+/* Return the total number of file infos */
+{
+    return CollCount (&FileInfos);
+}
+
+
+
+void AssignFileInfoIds (void)
+/* Remove unused file infos and assign the ids to the remaining ones */
+{
+    unsigned I, J;
+
+    /* Print all file infos */
+    for (I = 0, J = 0; I < CollCount (&FileInfos); ++I) {
+
+        /* Get the next file info */
+        FileInfo* FI = CollAtUnchecked (&FileInfos, I);
+
+        /* If it's unused, free it, otherwise assign the id and keep it */
+        if (CollCount (&FI->Modules) == 0) {
+            FreeFileInfo (FI);
+        } else {
+            FI->Id = J;
+            CollReplace (&FileInfos, FI, J++);
+        }
+    }
+
+    /* The new count is now in J */
+    FileInfos.Count = J;
+}
+
+
+
+void PrintDbgFileInfo (FILE* F)
+/* Output the file info to a debug info file */
+{
+    unsigned I, J;
+
+    /* Print all file infos */
+    for (I = 0; I < CollCount (&FileInfos); ++I) {
+
+        /* Get the file info */
+        const FileInfo* FI = CollAtUnchecked (&FileInfos, I);
+
+        /* Base info */
+        fprintf (F,
+                 "file\tid=%u,name=\"%s\",size=%lu,mtime=0x%08lX,mod=",
+                 FI->Id, GetString (FI->Name), FI->Size, FI->MTime);
+
+        /* Modules that use the file */
+        for (J = 0; J < CollCount (&FI->Modules); ++J) {
+
+            /* Get the module */
+            const ObjData* O = CollConstAt (&FI->Modules, J);
+
+            /* Output its id */
+            if (J > 0) {
+                fprintf (F, "+%u", O->Id);
+            } else {
+                fprintf (F, "%u", O->Id);
+            }
+        }
+
+        /* Terminate the output line */
+        fputc ('\n', F);
+    }
+}
+
+
+