X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Ffiletab.c;h=82e20ee70ecf1576123fb31a06d34cde673e4264;hb=93249045352c2949461e89d2c602600beb72d87d;hp=8448d44df9a3146b54a99f9e929d828e54c5e461;hpb=bb115c8ae2828eaff69016ca592079827bb7e0a3;p=cc65 diff --git a/src/ca65/filetab.c b/src/ca65/filetab.c index 8448d44df..82e20ee70 100644 --- a/src/ca65/filetab.c +++ b/src/ca65/filetab.c @@ -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 */ @@ -33,15 +33,42 @@ +#include +#include +#include + /* 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. + */ @@ -51,72 +78,95 @@ +/* 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); + } +} + +