1 /*****************************************************************************/
5 /* Source file line info structure */
9 /* (C) 2001-2011, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* 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 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* An invalid line info index */
57 #define INV_LINEINFO_INDEX UINT_MAX
59 /* Collection containing all line infos */
60 static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
62 /* Number of valid (=used) line infos in LineInfoColl */
63 static unsigned UsedLineInfoCount;
65 /* Entry in CurLineInfo */
66 typedef struct LineInfoSlot LineInfoSlot;
72 /* Dynamically allocated array of LineInfoSlots */
73 static LineInfoSlot* CurLineInfo;
74 static unsigned AllocatedSlots;
75 static unsigned UsedSlots;
79 /*****************************************************************************/
81 /*****************************************************************************/
85 static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos)
86 /* Create and return a new line info. Usage will be zero. */
89 LineInfo* LI = xmalloc (sizeof (LineInfo));
91 /* Initialize the fields */
94 LI->Index = INV_LINEINFO_INDEX;
97 /* Add the line info to the list of all line infos */
98 CollAppend (&LineInfoColl, LI);
100 /* Return the new struct */
106 /*****************************************************************************/
108 /*****************************************************************************/
112 void InitLineInfo (void)
113 /* Initialize the line infos */
115 static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER;
117 /* Increase the initial count of the line info collection */
118 CollGrow (&LineInfoColl, 200);
120 /* Allocate 8 slots */
122 CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
124 /* Initalize the predefined slots. Be sure to create a new LineInfo for
125 * the default source. This is necessary to allow error message to be
126 * generated without any input file open.
129 CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM; /* Count = 0 */
130 CurLineInfo[LI_SLOT_ASM].Info = NewLineInfo (LI_TYPE_ASM, &DefaultPos);
131 CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT; /* Count = 0 */
132 CurLineInfo[LI_SLOT_EXT].Info = 0;
137 int AllocLineInfoSlot (unsigned Type, unsigned Count)
138 /* Allocate a line info slot of the given type and return the slot index */
140 /* Grow the array if necessary */
141 if (UsedSlots >= AllocatedSlots) {
142 LineInfoSlot* NewLineInfo;
144 NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
145 memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
147 CurLineInfo = NewLineInfo;
150 /* Array is now big enough, add the new data */
151 CurLineInfo[UsedSlots].Type = LI_MAKE_TYPE(Type, Count);
152 CurLineInfo[UsedSlots].Info = 0;
154 /* Increment the count and return the index of the new slot */
155 return (int) UsedSlots++;
160 void FreeLineInfoSlot (int Slot)
161 /* Free the line info in the given slot. Note: Alloc/Free must be used in
165 /* Check the parameter */
166 PRECONDITION (Slot == (int) UsedSlots - 1);
168 /* Free the last entry */
169 CurLineInfo[Slot].Info = 0;
175 void GenLineInfo (int Slot, const FilePos* Pos)
176 /* Generate a new line info in the given slot */
178 /* Get a pointer to the slot */
179 LineInfoSlot* S = CurLineInfo + Slot;
181 /* Generate new data only if it is different from the existing. */
182 if (S->Info && CompareFilePos (&S->Info->Pos, Pos) == 0) {
187 /* Allocate new data */
188 S->Info = NewLineInfo (S->Type, Pos);
193 void ClearLineInfo (int Slot)
194 /* Clear the line info in the given slot */
196 /* Zero the pointer */
197 CurLineInfo[Slot].Info = 0;
202 void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage)
203 /* Return full line infos, that is line infos for all slots in LineInfos. The
204 * function will clear LineInfos before usage and will increment the usage
205 * counter by IncUsage for all line infos returned.
210 /* Clear the collection */
211 CollDeleteAll (LineInfos);
213 /* Copy all valid line infos to the collection */
214 for (I = 0; I < UsedSlots; ++I) {
216 /* Get the line info from the slot */
217 LineInfo* LI = CurLineInfo[I].Info;
219 /* Ignore empty slots */
221 LI->Usage += IncUsage;
222 CollAppend (LineInfos, LI);
229 LineInfo* ReleaseLineInfo (LineInfo* LI)
230 /* Decrease the reference count of the given line info and return it. The
231 * function will gracefully accept NULL pointers and do nothing in this case.
235 /* Cannot decrease below zero */
236 CHECK (LI->Usage != 0);
244 static int CmpLineInfo (void* Data attribute ((unused)),
245 const void* LI1_, const void* LI2_)
246 /* Compare function for the sort */
248 /* Cast the pointers */
249 const LineInfo* LI1 = LI1_;
250 const LineInfo* LI2 = LI2_;
252 /* Unreferenced line infos are always larger, otherwise sort by file,
253 * then by line, then by column.
255 if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
256 /* Both are either referenced or unreferenced */
257 return CompareFilePos (&LI1->Pos, &LI2->Pos);
259 if (LI1->Usage > 0) {
269 void WriteLineInfo (const Collection* LineInfos)
270 /* Write a list of line infos to the object file. MakeLineInfoIndex has to
276 /* Write the count */
277 ObjWriteVar (CollCount (LineInfos));
279 /* Write the line info indices */
280 for (I = 0; I < CollCount (LineInfos); ++I) {
282 /* Get a pointer to the line info */
283 const LineInfo* LI = CollConstAt (LineInfos, I);
285 /* Check the index */
286 CHECK (LI->Index != INV_LINEINFO_INDEX);
288 /* Write the index to the file */
289 ObjWriteVar (LI->Index);
295 void MakeLineInfoIndex (void)
296 /* Index the line infos */
300 /* Sort the line info list */
301 CollSort (&LineInfoColl, CmpLineInfo, 0);
303 /* Walk over the list, index the line infos and count the used ones */
304 UsedLineInfoCount = 0;
305 for (I = 0; I < CollCount (&LineInfoColl); ++I) {
306 /* Get a pointer to this line info */
307 LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
309 /* If it is invalid, terminate the loop. All unused line infos were
310 * placed at the end of the collection by the sort.
312 if (LI->Usage == 0) {
316 /* Index and count this one */
324 void WriteLineInfos (void)
325 /* Write a list of all line infos to the object file. */
329 /* Tell the object file module that we're about to write line infos */
330 ObjStartLineInfos ();
332 /* Write the line info count to the list */
333 ObjWriteVar (UsedLineInfoCount);
335 /* Walk over the list and write all line infos */
336 for (I = 0; I < UsedLineInfoCount; ++I) {
337 /* Get a pointer to this line info */
338 LineInfo* LI = CollAt (&LineInfoColl, I);
340 /* Write the type and count of the line info */
341 ObjWriteVar (LI->Type);
343 /* Write the source file position */
344 ObjWritePos (&LI->Pos);
347 /* End of line infos */