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 (const void* Entry);
65 /* Given a pointer to the user entry data, return a pointer to the key. */
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 FileType Type; /* Type of file */
92 unsigned long Size; /* Size of file */
93 unsigned long MTime; /* Time of last modification */
96 /* Array of all entries, listed by index */
97 static Collection FileTab = STATIC_COLLECTION_INITIALIZER;
99 /* Hash table functions */
100 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 (const void* Entry)
126 /* Given a pointer to the user entry data, return a pointer to the index */
128 return &((FileEntry*) Entry)->Name;
133 static int HT_Compare (const void* Key1, const void* Key2)
134 /* Compare two keys. The function must return a value less than zero if
135 * Key1 is smaller than Key2, zero if both are equal, and a value greater
136 * than zero if Key1 is greater then Key2.
139 return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
144 /*****************************************************************************/
146 /*****************************************************************************/
150 static FileEntry* NewFileEntry (unsigned Name, FileType Type,
151 unsigned long Size, unsigned long MTime)
152 /* Create a new FileEntry, insert it into the tables and return it */
154 /* Allocate memory for the entry */
155 FileEntry* F = xmalloc (sizeof (FileEntry));
157 /* Initialize the fields */
158 InitHashNode (&F->Node);
160 F->Index = CollCount (&FileTab) + 1; /* First file has index #1 */
165 /* Insert the file into the file table */
166 CollAppend (&FileTab, F);
168 /* Insert the entry into the hash table */
169 HT_Insert (&HashTab, F);
171 /* Return the new entry */
177 const StrBuf* GetFileName (unsigned Name)
178 /* Get the name of a file where the name index is known */
180 static const StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)");
185 /* Name was defined outside any file scope, use the name of the first
186 * file instead. Errors are then reported with a file position of
187 * line zero in the first file.
189 if (CollCount (&FileTab) == 0) {
190 /* No files defined until now */
193 F = CollConstAt (&FileTab, 0);
196 F = CollConstAt (&FileTab, Name-1);
198 return GetStrBuf (F->Name);
203 unsigned GetFileIndex (const StrBuf* Name)
204 /* Return the file index for the given file name. */
206 /* Get the string pool index from the name */
207 unsigned NameIdx = GetStrBufId (Name);
209 /* Search in the hash table for the name */
210 const FileEntry* F = HT_Find (&HashTab, &NameIdx);
212 /* If we don't have this index, print a diagnostic and use the main file */
214 Error ("File name `%m%p' not found in file table", Name);
223 unsigned AddFile (const StrBuf* Name, FileType Type,
224 unsigned long Size, unsigned long MTime)
225 /* Add a new file to the list of input files. Return the index of the file in
229 /* Create a new file entry and insert it into the tables */
230 FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);
232 /* Return the index */
238 void WriteFiles (void)
239 /* Write the list of input files to the object file */
243 /* Tell the obj file module that we're about to start the file list */
246 /* Write the file count */
247 ObjWriteVar (CollCount (&FileTab));
249 /* Write the file data */
250 for (I = 0; I < CollCount (&FileTab); ++I) {
251 /* Get a pointer to the entry */
252 const FileEntry* F = CollConstAt (&FileTab, I);
253 /* Write the fields */
254 ObjWriteVar (F->Name);
255 ObjWrite32 (F->MTime);
256 ObjWriteVar (F->Size);
259 /* Done writing files */
265 static void WriteDep (FILE* F, FileType Types)
266 /* Helper function. Writes all file names that match Types to the output */
270 /* Loop over all files */
271 for (I = 0; I < CollCount (&FileTab); ++I) {
273 const StrBuf* Filename;
275 /* Get the next input file */
276 const FileEntry* E = (const FileEntry*) CollAt (&FileTab, I);
278 /* Ignore it if it is not of the correct type */
279 if ((E->Type & Types) == 0) {
283 /* If this is not the first file, add a space */
288 /* Print the dependency */
289 Filename = GetStrBuf (E->Name);
290 fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename));
296 static void CreateDepFile (const char* Name, FileType Types)
297 /* Create a dependency file with the given name and place dependencies for
298 * all files with the given types there.
302 FILE* F = fopen (Name, "w");
304 Fatal ("Cannot open dependency file `%s': %s", Name, strerror (errno));
307 /* Print the output file followed by a tab char */
308 fprintf (F, "%s:\t", OutFile);
310 /* Write out the dependencies for the output file */
314 /* Write out a phony dependency for the included files */
318 /* Close the file, check for errors */
319 if (fclose (F) != 0) {
321 Fatal ("Cannot write to dependeny file (disk full?)");
327 void CreateDependencies (void)
328 /* Create dependency files requested by the user */
330 if (SB_NotEmpty (&DepName)) {
331 CreateDepFile (SB_GetConstBuf (&DepName),
332 FT_MAIN | FT_INCLUDE | FT_BINARY);
334 if (SB_NotEmpty (&FullDepName)) {
335 CreateDepFile (SB_GetConstBuf (&FullDepName),
336 FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO);