1 /*****************************************************************************/
5 /* Input file table for ca65 */
9 /* (C) 2000-2008 Ullrich von Bassewitz */
10 /* Roemerstrasse 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 /*****************************************************************************/
55 /*****************************************************************************/
57 /*****************************************************************************/
61 static unsigned HT_GenHash (const void* Key);
62 /* Generate the hash over a key. */
64 static const void* HT_GetKey (void* Entry);
65 /* Given a pointer to the user entry data, return a pointer to the key. */
67 static HashNode* HT_GetHashNode (void* Entry);
68 /* Given a pointer to the user entry data, return a pointer to the hash node */
70 static int HT_Compare (const void* Key1, const void* Key2);
71 /* Compare two keys. The function must return a value less than zero if
72 * Key1 is smaller than Key2, zero if both are equal, and a value greater
73 * than zero if Key1 is greater then Key2.
78 /*****************************************************************************/
80 /*****************************************************************************/
84 /* Number of entries in the table and the mask to generate the hash */
85 #define HASHTAB_MASK 0x1F
86 #define HASHTAB_COUNT (HASHTAB_MASK + 1)
88 /* An entry in the file table */
89 typedef struct FileEntry FileEntry;
92 unsigned Name; /* File name */
93 unsigned Index; /* Index of entry */
94 FileType Type; /* Type of file */
95 unsigned long Size; /* Size of file */
96 unsigned long MTime; /* Time of last modification */
99 /* Array of all entries, listed by index */
100 static Collection FileTab = STATIC_COLLECTION_INITIALIZER;
102 /* Hash table functions */
103 static const HashFunctions HashFunc = {
110 /* Hash table, hashed by name */
111 static HashTable HashTab = STATIC_HASHTABLE_INITIALIZER (HASHTAB_COUNT, &HashFunc);
115 /*****************************************************************************/
116 /* Hash table functions */
117 /*****************************************************************************/
121 static unsigned HT_GenHash (const void* Key)
122 /* Generate the hash over a key. */
124 return (*(const unsigned*)Key & HASHTAB_MASK);
129 static const void* HT_GetKey (void* Entry)
130 /* Given a pointer to the user entry data, return a pointer to the index */
132 return &((FileEntry*) Entry)->Name;
137 static HashNode* HT_GetHashNode (void* Entry)
138 /* Given a pointer to the user entry data, return a pointer to the hash node */
140 return &((FileEntry*) Entry)->Node;
145 static int HT_Compare (const void* Key1, const void* Key2)
146 /* Compare two keys. The function must return a value less than zero if
147 * Key1 is smaller than Key2, zero if both are equal, and a value greater
148 * than zero if Key1 is greater then Key2.
151 return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
156 /*****************************************************************************/
158 /*****************************************************************************/
162 static FileEntry* NewFileEntry (unsigned Name, FileType Type,
163 unsigned long Size, unsigned long MTime)
164 /* Create a new FileEntry, insert it into the tables and return it */
166 /* Allocate memory for the entry */
167 FileEntry* F = xmalloc (sizeof (FileEntry));
169 /* Initialize the fields */
170 InitHashNode (&F->Node, F);
172 F->Index = CollCount (&FileTab) + 1; /* First file has index #1 */
177 /* Insert the file into the file table */
178 CollAppend (&FileTab, F);
180 /* Insert the entry into the hash table */
181 HT_Insert (&HashTab, &F->Node);
183 /* Return the new entry */
189 const StrBuf* GetFileName (unsigned Name)
190 /* Get the name of a file where the name index is known */
192 static const StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)");
197 /* Name was defined outside any file scope, use the name of the first
198 * file instead. Errors are then reported with a file position of
199 * line zero in the first file.
201 if (CollCount (&FileTab) == 0) {
202 /* No files defined until now */
205 F = CollConstAt (&FileTab, 0);
208 F = CollConstAt (&FileTab, Name-1);
210 return GetStrBuf (F->Name);
215 unsigned GetFileIndex (const StrBuf* Name)
216 /* Return the file index for the given file name. */
218 /* Get the string pool index from the name */
219 unsigned NameIdx = GetStrBufId (Name);
221 /* Search in the hash table for the name */
222 FileEntry* F = HT_FindEntry (&HashTab, &NameIdx);
224 /* If we don't have this index, print a diagnostic and use the main file */
226 Error ("File name `%m%p' not found in file table", Name);
235 unsigned AddFile (const StrBuf* Name, FileType Type,
236 unsigned long Size, unsigned long MTime)
237 /* Add a new file to the list of input files. Return the index of the file in
241 /* Create a new file entry and insert it into the tables */
242 FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);
244 /* Return the index */
250 void WriteFiles (void)
251 /* Write the list of input files to the object file */
255 /* Tell the obj file module that we're about to start the file list */
258 /* Write the file count */
259 ObjWriteVar (CollCount (&FileTab));
261 /* Write the file data */
262 for (I = 0; I < CollCount (&FileTab); ++I) {
263 /* Get a pointer to the entry */
264 const FileEntry* F = CollConstAt (&FileTab, I);
265 /* Write the fields */
266 ObjWriteVar (F->Name);
267 ObjWrite32 (F->MTime);
268 ObjWrite32 (F->Size);
271 /* Done writing files */
277 static void WriteDep (FILE* F, FileType Types)
278 /* Helper function. Writes all file names that match Types to the output */
282 /* Loop over all files */
283 for (I = 0; I < CollCount (&FileTab); ++I) {
285 const StrBuf* Filename;
287 /* Get the next input file */
288 const FileEntry* E = (const FileEntry*) CollAt (&FileTab, I);
290 /* Ignore it if it is not of the correct type */
291 if ((E->Type & Types) == 0) {
295 /* If this is not the first file, add a space */
300 /* Print the dependency */
301 Filename = GetStrBuf (E->Name);
302 fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename));
308 static void CreateDepFile (const char* Name, FileType Types)
309 /* Create a dependency file with the given name and place dependencies for
310 * all files with the given types there.
314 FILE* F = fopen (Name, "w");
316 Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
319 /* Print the output file followed by a tab char */
320 fprintf (F, "%s:\t", OutFile);
322 /* Write out the dependencies for the output file */
326 /* Write out a phony dependency for the included files */
330 /* Close the file, check for errors */
331 if (fclose (F) != 0) {
333 Fatal ("Cannot write to dependeny file (disk full?)");
339 void CreateDependencies (void)
340 /* Create dependency files requested by the user */
342 if (SB_NotEmpty (&DepName)) {
343 CreateDepFile (SB_GetConstBuf (&DepName),
344 FT_MAIN | FT_INCLUDE | FT_BINARY);
346 if (SB_NotEmpty (&FullDepName)) {
347 CreateDepFile (SB_GetConstBuf (&FullDepName),
348 FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO);