1 /*****************************************************************************/
5 /* Input file table for ca65 */
9 /* (C) 2000-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
52 /*****************************************************************************/
54 /*****************************************************************************/
58 static unsigned HT_GenHash (const void* Key);
59 /* Generate the hash over a key. */
61 static const void* HT_GetKey (void* Entry);
62 /* Given a pointer to the user entry data, return a pointer to the key. */
64 static HashNode* HT_GetHashNode (void* Entry);
65 /* Given a pointer to the user entry data, return a pointer to the hash node */
67 static int HT_Compare (const void* Key1, const void* Key2);
68 /* Compare two keys. The function must return a value less than zero if
69 * Key1 is smaller than Key2, zero if both are equal, and a value greater
70 * than zero if Key1 is greater then Key2.
75 /*****************************************************************************/
77 /*****************************************************************************/
81 /* Number of entries in the table and the mask to generate the hash */
82 #define HASHTAB_MASK 0x1F
83 #define HASHTAB_COUNT (HASHTAB_MASK + 1)
85 /* An entry in the file table */
86 typedef struct FileEntry FileEntry;
89 unsigned Name; /* File name */
90 unsigned Index; /* Index of entry */
91 unsigned long Size; /* Size of file */
92 unsigned long MTime; /* Time of last modification */
95 /* Array of all entries, listed by index */
96 static Collection FileTab = STATIC_COLLECTION_INITIALIZER;
98 /* Hash table functions */
99 static const HashFunctions HashFunc = {
106 /* Hash table, hashed by name */
107 static HashTable HashTab = STATIC_HASHTABLE_INITIALIZER (HASHTAB_COUNT, &HashFunc);
111 /*****************************************************************************/
112 /* Hash table functions */
113 /*****************************************************************************/
117 static unsigned HT_GenHash (const void* Key)
118 /* Generate the hash over a key. */
120 return (*(const unsigned*)Key & HASHTAB_MASK);
125 static const void* HT_GetKey (void* Entry)
126 /* Given a pointer to the user entry data, return a pointer to the index */
128 return &((FileEntry*) Entry)->Name;
133 static HashNode* HT_GetHashNode (void* Entry)
134 /* Given a pointer to the user entry data, return a pointer to the hash node */
136 return &((FileEntry*) Entry)->Node;
141 static int HT_Compare (const void* Key1, const void* Key2)
142 /* Compare two keys. The function must return a value less than zero if
143 * Key1 is smaller than Key2, zero if both are equal, and a value greater
144 * than zero if Key1 is greater then Key2.
147 return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
152 /*****************************************************************************/
154 /*****************************************************************************/
158 static FileEntry* NewFileEntry (unsigned Name, unsigned long Size, unsigned long MTime)
159 /* Create a new FileEntry, insert it into the tables and return it */
161 /* Allocate memory for the entry */
162 FileEntry* F = xmalloc (sizeof (FileEntry));
164 /* Initialize the fields */
165 InitHashNode (&F->Node, F);
167 F->Index = CollCount (&FileTab) + 1; /* First file has index #1 */
171 /* Insert the file into the file table */
172 CollAppend (&FileTab, F);
174 /* Insert the entry into the hash table */
175 HT_Insert (&HashTab, &F->Node);
177 /* Return the new entry */
183 const char* GetFileName (unsigned Name)
184 /* Get the name of a file where the name index is known */
189 /* Name was defined outside any file scope, use the name of the first
190 * file instead. Errors are then reported with a file position of
191 * line zero in the first file.
193 if (CollCount (&FileTab) == 0) {
194 /* No files defined until now */
195 return "(outside file scope)";
197 F = CollConstAt (&FileTab, 0);
200 F = CollConstAt (&FileTab, Name-1);
202 return GetString (F->Name);
207 unsigned GetFileIndex (const char* Name)
208 /* Return the file index for the given file name. */
210 /* Get the string pool index from the name */
211 unsigned NameIdx = GetStringId (Name);
213 /* Search in the hash table for the name */
214 FileEntry* F = HT_FindEntry (&HashTab, &NameIdx);
216 /* If we don't have this index, print a diagnostic and use the main file */
218 Error (ERR_FILENAME_NOT_FOUND, Name);
227 unsigned AddFile (const char* Name, unsigned long Size, unsigned long MTime)
228 /* Add a new file to the list of input files. Return the index of the file in
232 /* Create a new file entry and insert it into the tables */
233 FileEntry* F = NewFileEntry (GetStringId (Name), Size, MTime);
235 /* Return the index */
241 void WriteFiles (void)
242 /* Write the list of input files to the object file */
246 /* Tell the obj file module that we're about to start the file list */
249 /* Write the file count */
250 ObjWriteVar (CollCount (&FileTab));
252 /* Write the file data */
253 for (I = 0; I < CollCount (&FileTab); ++I) {
254 /* Get a pointer to the entry */
255 const FileEntry* F = CollConstAt (&FileTab, I);
256 /* Write the fields */
257 ObjWriteVar (F->Name);
258 ObjWrite32 (F->MTime);
259 ObjWrite32 (F->Size);
262 /* Done writing files */