]> git.sur5r.net Git - cc65/blobdiff - src/ca65/filetab.c
Reverted r5835 because of Olivers changes to the asm includes.
[cc65] / src / ca65 / filetab.c
index 8448d44df9a3146b54a99f9e929d828e54c5e461..82e20ee70ecf1576123fb31a06d34cde673e4264 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 2000-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
 /* common */
 #include "check.h"
-#include "hashstr.h"
+#include "coll.h"
+#include "hashtab.h"
 #include "xmalloc.h"
 
 /* ca65 */
 #include "error.h"
-#include "objfile.h"
 #include "filetab.h"
+#include "global.h"
+#include "objfile.h"
+#include "spool.h"
+
+
+
+/*****************************************************************************/
+/*                                 Forwards                                  */
+/*****************************************************************************/
+
+
+
+static unsigned HT_GenHash (const void* Key);
+/* Generate the hash over a key. */
+
+static const void* HT_GetKey (const void* Entry);
+/* Given a pointer to the user entry data, return a pointer to the key. */
+
+static int HT_Compare (const void* Key1, const void* Key2);
+/* Compare two keys. The function must return a value less than zero if
+ * Key1 is smaller than Key2, zero if both are equal, and a value greater
+ * than zero if Key1 is greater then Key2.
+ */
 
 
 
 
 
 
+/* Number of entries in the table and the mask to generate the hash */
+#define HASHTAB_MASK    0x1F
+#define HASHTAB_COUNT   (HASHTAB_MASK + 1)
+
 /* An entry in the file table */
 typedef struct FileEntry FileEntry;
 struct FileEntry {
-    FileEntry*                 Next;           /* Next in hash list */
-    unsigned           Index;          /* Index of entry */
+    HashNode            Node;
+    unsigned            Name;           /* File name */
+    unsigned           Index;          /* Index of entry */
+    FileType            Type;           /* Type of file */
     unsigned long      Size;           /* Size of file */
     unsigned long      MTime;          /* Time of last modification */
-    char               Name[1];        /* Name, dynamically allocated */
 };
 
 /* Array of all entries, listed by index */
-static FileEntry**     FileTab   = 0;
-static unsigned                FileCount = 0;
-static unsigned        FileMax   = 0;
+static Collection FileTab = STATIC_COLLECTION_INITIALIZER;
+
+/* Hash table functions */
+static const HashFunctions HashFunc = {
+    HT_GenHash,
+    HT_GetKey,
+    HT_Compare
+};
 
 /* Hash table, hashed by name */
-#define HASHTAB_SIZE   31
-static FileEntry*      HashTab[HASHTAB_SIZE];
+static HashTable HashTab = STATIC_HASHTABLE_INITIALIZER (HASHTAB_COUNT, &HashFunc);
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                           Hash table functions                            */
 /*****************************************************************************/
 
 
 
-static FileEntry* NewFileEntry (const char* Name, unsigned long Size, unsigned long MTime)
-/* Create a new FileEntry, insert it into the tables and return it */
+static unsigned HT_GenHash (const void* Key)
+/* Generate the hash over a key. */
+{
+    return (*(const unsigned*)Key & HASHTAB_MASK);
+}
+
+
+
+static const void* HT_GetKey (const void* Entry)
+/* Given a pointer to the user entry data, return a pointer to the index */
+{
+    return &((FileEntry*) Entry)->Name;
+}
+
+
+
+static int HT_Compare (const void* Key1, const void* Key2)
+/* Compare two keys. The function must return a value less than zero if
+ * Key1 is smaller than Key2, zero if both are equal, and a value greater
+ * than zero if Key1 is greater then Key2.
+ */
 {
-    /* Get the length of the name */
-    unsigned Len = strlen (Name);
+    return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
+}
 
-    /* Get the hash over the name */
-    unsigned Hash = HashStr (Name) % HASHTAB_SIZE;
 
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+static FileEntry* NewFileEntry (unsigned Name, FileType Type,
+                                unsigned long Size, unsigned long MTime)
+/* Create a new FileEntry, insert it into the tables and return it */
+{
     /* Allocate memory for the entry */
-    FileEntry* F = xmalloc (sizeof (FileEntry) + Len);
+    FileEntry* F = xmalloc (sizeof (FileEntry));
 
     /* Initialize the fields */
-    F->Index   = FileCount+1;
+    InitHashNode (&F->Node);
+    F->Name     = Name;
+    F->Index   = CollCount (&FileTab) + 1;     /* First file has index #1 */
+    F->Type     = Type;
     F->Size    = Size;
     F->MTime   = MTime;
-    memcpy (F->Name, Name, Len+1);
-
-    /* Count the entries and grow the file table if needed */
-    if (FileCount >= FileMax) {
-       /* We need to grow the table. Create a new one. */
-       unsigned NewFileMax   = (FileMax == 0)? 32 : FileMax * 2;
-               FileEntry** NewFileTab = xmalloc (sizeof (FileEntry*) * NewFileMax);
-
-       /* Copy the old entries */
-       memcpy (NewFileTab, FileTab, sizeof (FileEntry*) * FileCount);
-
-       /* Use the new table */
-       xfree (FileTab);
-       FileTab = NewFileTab;
-       FileMax = NewFileMax;
-    }
 
     /* Insert the file into the file table */
-    FileTab [FileCount++] = F;
+    CollAppend (&FileTab, F);
 
     /* Insert the entry into the hash table */
-    F->Next = HashTab[Hash];
-    HashTab[Hash] = F;
+    HT_Insert (&HashTab, F);
 
     /* Return the new entry */
     return F;
@@ -124,60 +174,60 @@ static FileEntry* NewFileEntry (const char* Name, unsigned long Size, unsigned l
 
 
 
-const char* GetFileName (unsigned Name)
+const StrBuf* GetFileName (unsigned Name)
 /* Get the name of a file where the name index is known */
 {
-    PRECONDITION (Name <= FileCount);
+    static const StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)");
+
+    const FileEntry* F;
+
     if (Name == 0) {
        /* Name was defined outside any file scope, use the name of the first
         * file instead. Errors are then reported with a file position of
         * line zero in the first file.
         */
-       if (FileCount == 0) {
+       if (CollCount (&FileTab) == 0) {
            /* No files defined until now */
-                   return "(outside file scope)";
+            return &ErrorMsg;
        } else {
-                   return FileTab [0]->Name;
+            F = CollConstAt (&FileTab, 0);
        }
     } else {
-        return FileTab [Name-1]->Name;
+        F = CollConstAt (&FileTab, Name-1);
     }
+    return GetStrBuf (F->Name);
 }
 
 
 
-unsigned GetFileIndex (const char* Name)
+unsigned GetFileIndex (const StrBuf* Name)
 /* Return the file index for the given file name. */
 {
-    /* Get the hash over the name */
-    unsigned Hash = HashStr (Name) % HASHTAB_SIZE;
-
-    /* Search the linear hash list */
-    FileEntry* F = HashTab[Hash];
-    while (F) {
-       /* Is it this one? */
-       if (strcmp (Name, F->Name) == 0) {
-           /* Found, return the index */
-           return F->Index;
-       }
-       /* No, check next */
-       F = F->Next;
-    }
+    /* Get the string pool index from the name */
+    unsigned NameIdx = GetStrBufId (Name);
+
+    /* Search in the hash table for the name */
+    const FileEntry* F = HT_Find (&HashTab, &NameIdx);
 
-    /* Not found, use main file */
-    Error (ERR_FILENAME_NOT_FOUND, Name);
-    return 0;
+    /* If we don't have this index, print a diagnostic and use the main file */
+    if (F == 0) {
+        Error ("File name `%m%p' not found in file table", Name);
+        return 0;
+    } else {
+        return F->Index;
+    }
 }
 
 
 
-unsigned AddFile (const char* Name, unsigned long Size, unsigned long MTime)
+unsigned AddFile (const StrBuf* Name, FileType Type,
+                  unsigned long Size, unsigned long MTime)
 /* Add a new file to the list of input files. Return the index of the file in
  * the table.
  */
 {
     /* Create a new file entry and insert it into the tables */
-    FileEntry* F = NewFileEntry (Name, Size, MTime);
+    FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);
 
     /* Return the index */
     return F->Index;
@@ -194,16 +244,16 @@ void WriteFiles (void)
     ObjStartFiles ();
 
     /* Write the file count */
-    ObjWriteVar (FileCount);
+    ObjWriteVar (CollCount (&FileTab));
 
     /* Write the file data */
-    for (I = 0; I < FileCount; ++I) {
+    for (I = 0; I < CollCount (&FileTab); ++I) {
        /* Get a pointer to the entry */
-       FileEntry* F = FileTab[I];
+       const FileEntry* F = CollConstAt (&FileTab, I);
        /* Write the fields */
+       ObjWriteVar (F->Name);
        ObjWrite32 (F->MTime);
-       ObjWrite32 (F->Size);
-       ObjWriteStr (F->Name);
+               ObjWriteVar (F->Size);
     }
 
     /* Done writing files */
@@ -212,3 +262,79 @@ void WriteFiles (void)
 
 
 
+static void WriteDep (FILE* F, FileType Types)
+/* Helper function. Writes all file names that match Types to the output */
+{
+    unsigned I;
+
+    /* Loop over all files */
+    for (I = 0; I < CollCount (&FileTab); ++I) {
+
+        const StrBuf* Filename;
+
+       /* Get the next input file */
+               const FileEntry* E = (const FileEntry*) CollAt (&FileTab, I);
+
+        /* Ignore it if it is not of the correct type */
+        if ((E->Type & Types) == 0) {
+            continue;
+        }
+
+       /* If this is not the first file, add a space */
+               if (I > 0) {
+            fputc (' ', F);
+        }
+
+       /* Print the dependency */
+        Filename = GetStrBuf (E->Name);
+        fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename));
+    }
+}
+
+
+
+static void CreateDepFile (const char* Name, FileType Types)
+/* Create a dependency file with the given name and place dependencies for
+ * all files with the given types there.
+ */
+{
+    /* Open the file */
+    FILE* F = fopen (Name, "w");
+    if (F == 0) {
+       Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
+    }
+
+    /* Print the output file followed by a tab char */
+    fprintf (F, "%s:\t", OutFile);
+
+    /* Write out the dependencies for the output file */
+    WriteDep (F, Types);
+    fputs ("\n\n", F);
+
+    /* Write out a phony dependency for the included files */
+    WriteDep (F, Types);
+    fputs (":\n\n", F);
+
+    /* Close the file, check for errors */
+    if (fclose (F) != 0) {
+       remove (Name);
+       Fatal ("Cannot write to dependeny file (disk full?)");
+    }
+}
+
+
+
+void CreateDependencies (void)
+/* Create dependency files requested by the user */
+{
+    if (SB_NotEmpty (&DepName)) {
+        CreateDepFile (SB_GetConstBuf (&DepName),
+                       FT_MAIN | FT_INCLUDE | FT_BINARY);
+    }
+    if (SB_NotEmpty (&FullDepName)) {
+        CreateDepFile (SB_GetConstBuf (&FullDepName),
+                       FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO);
+    }
+}
+
+