1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* lineinfo.h */ |
4 | /* */ |
5 | /* Source file line info structure */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2001-2012, 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 "check.h" |
38 | #include "lidefs.h" |
39 | #include "xmalloc.h" |
40 | |
41 | /* ld65 */ |
42 | #include "error.h" |
43 | #include "fileinfo.h" |
44 | #include "fileio.h" |
45 | #include "lineinfo.h" |
46 | #include "objdata.h" |
47 | #include "segments.h" |
48 | |
49 | |
50 | |
51 | /*****************************************************************************/ |
52 | /* Code */ |
53 | /*****************************************************************************/ |
54 | |
55 | |
56 | |
57 | static LineInfo* NewLineInfo (void) |
58 | /* Create and return a new LineInfo struct with mostly empty fields */ |
59 | { |
60 | /* Allocate memory */ |
61 | LineInfo* LI = xmalloc (sizeof (LineInfo)); |
62 | |
63 | /* Initialize the fields */ |
64 | LI->Id = ~0U; |
65 | LI->File = 0; |
66 | LI->Type = LI_MAKE_TYPE (LI_TYPE_ASM, 0); |
67 | LI->Pos.Name = INVALID_STRING_ID; |
68 | LI->Pos.Line = 0; |
69 | LI->Pos.Col = 0; |
70 | LI->Spans = 0; |
71 | |
72 | /* Return the new struct */ |
73 | return LI; |
74 | } |
75 | |
76 | |
77 | |
78 | void FreeLineInfo (LineInfo* LI) |
79 | /* Free a LineInfo structure. */ |
80 | { |
81 | /* Free the span list */ |
82 | xfree (LI->Spans); |
83 | |
84 | /* Free the structure itself */ |
85 | xfree (LI); |
86 | } |
87 | |
88 | |
89 | |
90 | LineInfo* DupLineInfo (const LineInfo* LI) |
91 | /* Creates a duplicate of a line info structure */ |
92 | { |
93 | /* Allocate memory */ |
94 | LineInfo* New = xmalloc (sizeof (LineInfo)); |
95 | |
96 | /* Copy the fields (leave id invalid) */ |
97 | New->Id = LI->Id; |
98 | New->File = LI->File; |
99 | New->Type = LI->Type; |
100 | New->Pos = LI->Pos; |
101 | New->Spans = DupSpanList (LI->Spans); |
102 | |
103 | /* Return the copy */ |
104 | return New; |
105 | } |
106 | |
107 | |
108 | |
109 | LineInfo* GenLineInfo (const FilePos* Pos) |
110 | /* Generate a new (internally used) line info with the given information */ |
111 | { |
112 | /* Create a new LineInfo struct */ |
113 | LineInfo* LI = NewLineInfo (); |
114 | |
115 | /* Initialize the fields in the new LineInfo */ |
116 | LI->Pos = *Pos; |
117 | |
118 | /* Return the struct read */ |
119 | return LI; |
120 | } |
121 | |
122 | |
123 | |
124 | LineInfo* ReadLineInfo (FILE* F, ObjData* O) |
125 | /* Read a line info from a file and return it */ |
126 | { |
127 | /* Create a new LineInfo struct */ |
128 | LineInfo* LI = NewLineInfo (); |
129 | |
130 | /* Read/fill the fields in the new LineInfo */ |
131 | LI->Pos.Line = ReadVar (F); |
132 | LI->Pos.Col = ReadVar (F); |
133 | LI->File = CollAt (&O->Files, ReadVar (F)); |
134 | LI->Pos.Name = LI->File->Name; |
135 | LI->Type = ReadVar (F); |
136 | LI->Spans = ReadSpanList (F); |
137 | |
138 | /* Return the struct read */ |
139 | return LI; |
140 | } |
141 | |
142 | |
143 | |
144 | void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos) |
145 | /* Read a list of line infos stored as a list of indices in the object file, |
146 | ** make real line infos from them and place them into the passed collection. |
147 | */ |
148 | { |
149 | /* Read the number of line info indices that follow */ |
150 | unsigned LineInfoCount = ReadVar (F); |
151 | |
152 | /* Grow the collection as needed */ |
153 | CollGrow (LineInfos, LineInfoCount); |
154 | |
155 | /* Read the line infos and resolve them */ |
156 | while (LineInfoCount--) { |
157 | |
158 | /* Read an index */ |
159 | unsigned LineInfoIndex = ReadVar (F); |
160 | |
161 | /* The line info index was written by the assembler and must |
162 | ** therefore be part of the line infos read from the object file. |
163 | */ |
164 | if (LineInfoIndex >= CollCount (&O->LineInfos)) { |
165 | Internal ("Invalid line info index %u in module '%s' - max is %u" , |
166 | LineInfoIndex, |
167 | GetObjFileName (O), |
168 | CollCount (&O->LineInfos)); |
169 | } |
170 | |
171 | /* Add the line info to the collection */ |
172 | CollAppend (LineInfos, CollAt (&O->LineInfos, LineInfoIndex)); |
173 | } |
174 | } |
175 | |
176 | |
177 | |
178 | const LineInfo* GetAsmLineInfo (const Collection* LineInfos) |
179 | /* Find a line info of type LI_TYPE_ASM and count zero in the given collection |
180 | ** and return it. Return NULL if no such line info was found. |
181 | */ |
182 | { |
183 | unsigned I; |
184 | |
185 | /* Search for a line info of LI_TYPE_ASM */ |
186 | for (I = 0; I < CollCount (LineInfos); ++I) { |
187 | const LineInfo* LI = CollConstAt (LineInfos, I); |
188 | if (LI->Type == LI_MAKE_TYPE (LI_TYPE_ASM, 0)) { |
189 | return LI; |
190 | } |
191 | } |
192 | |
193 | /* Not found */ |
194 | return 0; |
195 | } |
196 | |
197 | |
198 | |
199 | unsigned LineInfoCount (void) |
200 | /* Return the total number of line infos */ |
201 | { |
202 | /* Walk over all object files */ |
203 | unsigned I; |
204 | unsigned Count = 0; |
205 | for (I = 0; I < CollCount (&ObjDataList); ++I) { |
206 | |
207 | /* Get this object file */ |
208 | const ObjData* O = CollAtUnchecked (&ObjDataList, I); |
209 | |
210 | /* Count spans */ |
211 | Count += CollCount (&O->LineInfos); |
212 | } |
213 | |
214 | return Count; |
215 | } |
216 | |
217 | |
218 | |
219 | void AssignLineInfoIds (void) |
220 | /* Assign the ids to the line infos */ |
221 | { |
222 | unsigned I, J; |
223 | |
224 | /* Walk over all line infos */ |
225 | unsigned Id = 0; |
226 | for (I = 0; I < CollCount (&ObjDataList); ++I) { |
227 | |
228 | /* Get the object file */ |
229 | ObjData* O = CollAtUnchecked (&ObjDataList, I); |
230 | |
231 | /* Output the line infos */ |
232 | for (J = 0; J < CollCount (&O->LineInfos); ++J) { |
233 | |
234 | /* Get this line info */ |
235 | LineInfo* LI = CollAtUnchecked (&O->LineInfos, J); |
236 | |
237 | /* Assign the id */ |
238 | LI->Id = Id++; |
239 | } |
240 | } |
241 | } |
242 | |
243 | |
244 | |
245 | void PrintDbgLineInfo (FILE* F) |
246 | /* Output the line infos to a debug info file */ |
247 | { |
248 | unsigned I, J; |
249 | |
250 | /* Print line infos from all modules we have linked into the output file */ |
251 | for (I = 0; I < CollCount (&ObjDataList); ++I) { |
252 | |
253 | /* Get the object file */ |
254 | const ObjData* O = CollAtUnchecked (&ObjDataList, I); |
255 | |
256 | /* Output the line infos */ |
257 | for (J = 0; J < CollCount (&O->LineInfos); ++J) { |
258 | |
259 | /* Get this line info */ |
260 | const LineInfo* LI = CollConstAt (&O->LineInfos, J); |
261 | |
262 | /* Get the line info type and count */ |
263 | unsigned Type = LI_GET_TYPE (LI->Type); |
264 | unsigned Count = LI_GET_COUNT (LI->Type); |
265 | |
266 | /* Print the start of the line */ |
267 | fprintf (F, |
268 | "line\tid=%u,file=%u,line=%u" , |
269 | LI->Id, LI->File->Id, GetSourceLine (LI)); |
270 | |
271 | /* Print type if not LI_TYPE_ASM and count if not zero */ |
272 | if (Type != LI_TYPE_ASM) { |
273 | fprintf (F, ",type=%u" , Type); |
274 | } |
275 | if (Count != 0) { |
276 | fprintf (F, ",count=%u" , Count); |
277 | } |
278 | |
279 | /* Add spans if the line info has it */ |
280 | PrintDbgSpanList (F, O, LI->Spans); |
281 | |
282 | /* Terminate line */ |
283 | fputc ('\n', F); |
284 | } |
285 | } |
286 | } |
287 | |