]> git.sur5r.net Git - cc65/blob - src/ld65/fileinfo.c
add gotox, gotoy, and gotoxy
[cc65] / src / ld65 / fileinfo.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                fileinfo.c                                 */
4 /*                                                                           */
5 /*                        Source file info structure                         */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2001-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 /* common */
37 #include "coll.h"
38 #include "xmalloc.h"
39
40 /* ld65 */
41 #include "fileio.h"
42 #include "fileinfo.h"
43 #include "objdata.h"
44 #include "spool.h"
45
46
47
48 /*****************************************************************************/
49 /*                                   Data                                    */
50 /*****************************************************************************/
51
52
53
54 /* A list of all file infos without duplicates */
55 static Collection FileInfos = STATIC_COLLECTION_INITIALIZER;
56
57
58
59 /*****************************************************************************/
60 /*                                   Code                                    */
61 /*****************************************************************************/
62
63
64
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.
70  */
71 {
72     /* Do a binary search */
73     int Lo = 0;
74     int Hi = (int) CollCount (&FileInfos) - 1;
75     int Found = 0;
76     while (Lo <= Hi) {
77
78         /* Mid of range */
79         int Cur = (Lo + Hi) / 2;
80
81         /* Get item */
82         FileInfo* CurItem = CollAt (&FileInfos, Cur);
83
84         /* Found? */
85         if (CurItem->Name < Name) {
86             Lo = Cur + 1;
87         } else {
88             Hi = Cur - 1;
89             /* Since we may have duplicates, repeat the search until we've
90              * the first item that has a match.
91              */
92             if (CurItem->Name == Name) {
93                 Found = 1;
94             }
95         }
96     }
97
98     /* Pass back the index. This is also the insert position */
99     *Index = Lo;
100     return Found;
101 }
102
103
104
105 static FileInfo* NewFileInfo (unsigned Name, unsigned long MTime, unsigned long Size)
106 /* Allocate and initialize a new FileInfo struct and return it */
107 {
108     /* Allocate memory */
109     FileInfo* FI = xmalloc (sizeof (FileInfo));
110
111     /* Initialize stuff */
112     FI->Id      = ~0U;
113     FI->Name    = Name;
114     FI->MTime   = MTime;
115     FI->Size    = Size;
116     FI->Modules = EmptyCollection;
117
118     /* Return the new struct */
119     return FI;
120 }
121
122
123
124 static void FreeFileInfo (FileInfo* FI)
125 /* Free a file info structure */
126 {
127     /* Free the collection */
128     DoneCollection (&FI->Modules);
129
130     /* Free memory for the structure */
131     xfree (FI);
132 }
133
134
135
136 FileInfo* ReadFileInfo (FILE* F, ObjData* O)
137 /* Read a file info from a file and return it */
138 {
139     FileInfo* FI;
140
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);
145
146     /* Search for the first entry with this name */
147     unsigned Index;
148     if (FindFileInfo (Name, &Index)) {
149
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.
154          */
155         FI = CollAt (&FileInfos, Index);
156         while (1) {
157
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);
162                 return FI;
163             }
164
165             /* Check the next one */
166             if (++Index >= CollCount (&FileInfos)) {
167                 /* Nothing left */
168                 break;
169             }
170             FI = CollAt (&FileInfos, Index);
171
172             /* Done if the name differs */
173             if (FI->Name != Name) {
174                 break;
175             }
176         }
177     }
178
179     /* Not found. Allocate a new FileInfo structure */
180     FI = NewFileInfo (Name, MTime, Size);
181
182     /* Remember that this module uses the file info */
183     CollAppend (&FI->Modules, O);
184
185     /* Insert the file info in our global list. Index points to the insert
186      * position.
187      */
188     CollInsert (&FileInfos, FI, Index);
189
190     /* Return the new struct */
191     return FI;
192 }
193
194
195
196 unsigned FileInfoCount (void)
197 /* Return the total number of file infos */
198 {
199     return CollCount (&FileInfos);
200 }
201
202
203
204 void AssignFileInfoIds (void)
205 /* Remove unused file infos and assign the ids to the remaining ones */
206 {
207     unsigned I, J;
208
209     /* Print all file infos */
210     for (I = 0, J = 0; I < CollCount (&FileInfos); ++I) {
211
212         /* Get the next file info */
213         FileInfo* FI = CollAtUnchecked (&FileInfos, I);
214
215         /* If it's unused, free it, otherwise assign the id and keep it */
216         if (CollCount (&FI->Modules) == 0) {
217             FreeFileInfo (FI);
218         } else {
219             FI->Id = J;
220             CollReplace (&FileInfos, FI, J++);
221         }
222     }
223
224     /* The new count is now in J */
225     FileInfos.Count = J;
226 }
227
228
229
230 void PrintDbgFileInfo (FILE* F)
231 /* Output the file info to a debug info file */
232 {
233     unsigned I, J;
234
235     /* Print all file infos */
236     for (I = 0; I < CollCount (&FileInfos); ++I) {
237
238         /* Get the file info */
239         const FileInfo* FI = CollAtUnchecked (&FileInfos, I);
240
241         /* Base info */
242         fprintf (F,
243                  "file\tid=%u,name=\"%s\",size=%lu,mtime=0x%08lX,mod=",
244                  FI->Id, GetString (FI->Name), FI->Size, FI->MTime);
245
246         /* Modules that use the file */
247         for (J = 0; J < CollCount (&FI->Modules); ++J) {
248
249             /* Get the module */
250             const ObjData* O = CollConstAt (&FI->Modules, J);
251
252             /* Output its id */
253             if (J > 0) {
254                 fprintf (F, "+%u", O->Id);
255             } else {
256                 fprintf (F, "%u", O->Id);
257             }
258         }
259
260         /* Terminate the output line */
261         fputc ('\n', F);
262     }
263 }
264
265
266