1 /*****************************************************************************/
5 /* Source file info structure */
9 /* (C) 2001-2011, 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 /*****************************************************************************/
48 /*****************************************************************************/
50 /*****************************************************************************/
54 /* A list of all file infos without duplicates */
55 static Collection FileInfos = STATIC_COLLECTION_INITIALIZER;
59 /*****************************************************************************/
61 /*****************************************************************************/
65 static int FindFileInfo (unsigned Name, unsigned* Index)
66 /* Find the FileInfo for a given file name. The function returns true if the
67 * name was found. In this case, Index contains the index of the first item
68 * that matches. If the item wasn't found, the function returns false and
69 * Index contains the insert position for FileName.
72 /* Do a binary search */
74 int Hi = (int) CollCount (&FileInfos) - 1;
79 int Cur = (Lo + Hi) / 2;
82 FileInfo* CurItem = CollAt (&FileInfos, Cur);
85 if (CurItem->Name < Name) {
89 /* Since we may have duplicates, repeat the search until we've
90 * the first item that has a match.
92 if (CurItem->Name == Name) {
98 /* Pass back the index. This is also the insert position */
105 static FileInfo* NewFileInfo (unsigned Name, unsigned long MTime, unsigned long Size)
106 /* Allocate and initialize a new FileInfo struct and return it */
108 /* Allocate memory */
109 FileInfo* FI = xmalloc (sizeof (FileInfo));
111 /* Initialize stuff */
116 FI->Modules = EmptyCollection;
118 /* Return the new struct */
124 static void FreeFileInfo (FileInfo* FI)
125 /* Free a file info structure */
127 /* Free the collection */
128 DoneCollection (&FI->Modules);
130 /* Free memory for the structure */
136 FileInfo* ReadFileInfo (FILE* F, ObjData* O)
137 /* Read a file info from a file and return it */
141 /* Read the fields from the file */
142 unsigned Name = MakeGlobalStringId (O, ReadVar (F));
143 unsigned long MTime = Read32 (F);
144 unsigned long Size = ReadVar (F);
146 /* Search for the first entry with this name */
148 if (FindFileInfo (Name, &Index)) {
150 /* We have at least one such entry. Try all of them and, if size and
151 * modification time matches, return the first match. When the loop
152 * is terminated without finding an entry, Index points one behind
153 * the last entry with the name, which is the perfect insert position.
155 FI = CollAt (&FileInfos, Index);
158 /* Check size and modification time stamp */
159 if (FI->Size == Size && FI->MTime == MTime) {
160 /* Remember that the modules uses this file info, then return it */
161 CollAppend (&FI->Modules, O);
165 /* Check the next one */
166 if (++Index >= CollCount (&FileInfos)) {
170 FI = CollAt (&FileInfos, Index);
172 /* Done if the name differs */
173 if (FI->Name != Name) {
179 /* Not found. Allocate a new FileInfo structure */
180 FI = NewFileInfo (Name, MTime, Size);
182 /* Remember that this module uses the file info */
183 CollAppend (&FI->Modules, O);
185 /* Insert the file info in our global list. Index points to the insert
188 CollInsert (&FileInfos, FI, Index);
190 /* Return the new struct */
196 unsigned FileInfoCount (void)
197 /* Return the total number of file infos */
199 return CollCount (&FileInfos);
204 void AssignFileInfoIds (void)
205 /* Remove unused file infos and assign the ids to the remaining ones */
209 /* Print all file infos */
210 for (I = 0, J = 0; I < CollCount (&FileInfos); ++I) {
212 /* Get the next file info */
213 FileInfo* FI = CollAtUnchecked (&FileInfos, I);
215 /* If it's unused, free it, otherwise assign the id and keep it */
216 if (CollCount (&FI->Modules) == 0) {
220 CollReplace (&FileInfos, FI, J++);
224 /* The new count is now in J */
230 void PrintDbgFileInfo (FILE* F)
231 /* Output the file info to a debug info file */
235 /* Print all file infos */
236 for (I = 0; I < CollCount (&FileInfos); ++I) {
238 /* Get the file info */
239 const FileInfo* FI = CollAtUnchecked (&FileInfos, I);
243 "file\tid=%u,name=\"%s\",size=%lu,mtime=0x%08lX,mod=",
244 FI->Id, GetString (FI->Name), FI->Size, FI->MTime);
246 /* Modules that use the file */
247 for (J = 0; J < CollCount (&FI->Modules); ++J) {
250 const ObjData* O = CollConstAt (&FI->Modules, J);
254 fprintf (F, "+%u", O->Id);
256 fprintf (F, "%u", O->Id);
260 /* Terminate the output line */