1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* fileio.c */ |
4 | /* */ |
5 | /* File I/O for the od65 object file dump utility */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 1998-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 | #include <string.h> |
37 | #include <errno.h> |
38 | |
39 | /* common */ |
40 | #include "xmalloc.h" |
41 | |
42 | /* od65 */ |
43 | #include "error.h" |
44 | #include "fileio.h" |
45 | |
46 | |
47 | |
48 | /*****************************************************************************/ |
49 | /* Code */ |
50 | /*****************************************************************************/ |
51 | |
52 | |
53 | |
54 | void FileSetPos (FILE* F, unsigned long Pos) |
55 | /* Seek to the given absolute position, fail on errors */ |
56 | { |
57 | if (fseek (F, Pos, SEEK_SET) != 0) { |
58 | Error ("Cannot seek: %s" , strerror (errno)); |
59 | } |
60 | } |
61 | |
62 | |
63 | |
64 | unsigned long FileGetPos (FILE* F) |
65 | /* Return the current file position, fail on errors */ |
66 | { |
67 | long Pos = ftell (F); |
68 | if (Pos < 0) { |
69 | Error ("Error in ftell: %s" , strerror (errno)); |
70 | } |
71 | return Pos; |
72 | } |
73 | |
74 | |
75 | |
76 | unsigned Read8 (FILE* F) |
77 | /* Read an 8 bit value from the file */ |
78 | { |
79 | int C = getc (F); |
80 | if (C == EOF) { |
81 | Error ("Read error (file corrupt?)" ); |
82 | } |
83 | return C; |
84 | } |
85 | |
86 | |
87 | |
88 | unsigned Read16 (FILE* F) |
89 | /* Read a 16 bit value from the file */ |
90 | { |
91 | unsigned Lo = Read8 (F); |
92 | unsigned Hi = Read8 (F); |
93 | return (Hi << 8) | Lo; |
94 | } |
95 | |
96 | |
97 | |
98 | unsigned long Read24 (FILE* F) |
99 | /* Read a 24 bit value from the file */ |
100 | { |
101 | unsigned long Lo = Read16 (F); |
102 | unsigned long Hi = Read8 (F); |
103 | return (Hi << 16) | Lo; |
104 | } |
105 | |
106 | |
107 | |
108 | unsigned long Read32 (FILE* F) |
109 | /* Read a 32 bit value from the file */ |
110 | { |
111 | unsigned long Lo = Read16 (F); |
112 | unsigned long Hi = Read16 (F); |
113 | return (Hi << 16) | Lo; |
114 | } |
115 | |
116 | |
117 | |
118 | long Read32Signed (FILE* F) |
119 | /* Read a 32 bit value from the file. Sign extend the value. */ |
120 | { |
121 | /* Read a 32 bit value */ |
122 | unsigned long V = Read32 (F); |
123 | |
124 | /* Sign extend the value */ |
125 | if (V & 0x80000000UL) { |
126 | /* Signed value */ |
127 | V |= ~0xFFFFFFFFUL; |
128 | } |
129 | |
130 | /* Return it as a long */ |
131 | return (long) V; |
132 | } |
133 | |
134 | |
135 | |
136 | unsigned long ReadVar (FILE* F) |
137 | /* Read a variable size value from the file */ |
138 | { |
139 | /* The value was written to the file in 7 bit chunks LSB first. If there |
140 | ** are more bytes, bit 8 is set, otherwise it is clear. |
141 | */ |
142 | unsigned char C; |
143 | unsigned long V = 0; |
144 | unsigned Shift = 0; |
145 | do { |
146 | /* Read one byte */ |
147 | C = Read8 (F); |
148 | /* Encode it into the target value */ |
149 | V |= ((unsigned long)(C & 0x7F)) << Shift; |
150 | /* Next value */ |
151 | Shift += 7; |
152 | } while (C & 0x80); |
153 | |
154 | /* Return the value read */ |
155 | return V; |
156 | } |
157 | |
158 | |
159 | |
160 | char* ReadStr (FILE* F) |
161 | /* Read a string from the file into a malloced area */ |
162 | { |
163 | /* Read the length */ |
164 | unsigned Len = ReadVar (F); |
165 | |
166 | /* Allocate memory */ |
167 | char* Str = xmalloc (Len + 1); |
168 | |
169 | /* Read the string itself */ |
170 | ReadData (F, Str, Len); |
171 | |
172 | /* Terminate the string and return it */ |
173 | Str [Len] = '\0'; |
174 | return Str; |
175 | } |
176 | |
177 | |
178 | |
179 | FilePos* ReadFilePos (FILE* F, FilePos* Pos) |
180 | /* Read a file position from the file */ |
181 | { |
182 | /* Read the data fields */ |
183 | Pos->Line = ReadVar (F); |
184 | Pos->Col = ReadVar (F); |
185 | Pos->Name = ReadVar (F); |
186 | return Pos; |
187 | } |
188 | |
189 | |
190 | |
191 | void* ReadData (FILE* F, void* Data, unsigned Size) |
192 | /* Read data from the file */ |
193 | { |
194 | /* Accept zero sized reads */ |
195 | if (Size > 0) { |
196 | if (fread (Data, 1, Size, F) != Size) { |
197 | Error ("Read error (file corrupt?)" ); |
198 | } |
199 | } |
200 | return Data; |
201 | } |
202 | |
203 | |
204 | |
205 | void (FILE* F, ObjHeader* H) |
206 | /* Read an object file header from the file */ |
207 | { |
208 | /* Read all fields */ |
209 | H->Magic = Read32 (F); |
210 | H->Version = Read16 (F); |
211 | H->Flags = Read16 (F); |
212 | H->OptionOffs = Read32 (F); |
213 | H->OptionSize = Read32 (F); |
214 | H->FileOffs = Read32 (F); |
215 | H->FileSize = Read32 (F); |
216 | H->SegOffs = Read32 (F); |
217 | H->SegSize = Read32 (F); |
218 | H->ImportOffs = Read32 (F); |
219 | H->ImportSize = Read32 (F); |
220 | H->ExportOffs = Read32 (F); |
221 | H->ExportSize = Read32 (F); |
222 | H->DbgSymOffs = Read32 (F); |
223 | H->DbgSymSize = Read32 (F); |
224 | H->LineInfoOffs = Read32 (F); |
225 | H->LineInfoSize = Read32 (F); |
226 | H->StrPoolOffs = Read32 (F); |
227 | H->StrPoolSize = Read32 (F); |
228 | H->AssertOffs = Read32 (F); |
229 | H->AssertSize = Read32 (F); |
230 | H->ScopeOffs = Read32 (F); |
231 | H->ScopeSize = Read32 (F); |
232 | H->SpanOffs = Read32 (F); |
233 | H->SpanSize = Read32 (F); |
234 | } |
235 | |
236 | |
237 | |
238 | void ReadStrPool (FILE* F, Collection* C) |
239 | /* Read a string pool from the current position into C. */ |
240 | { |
241 | /* The number of strings is the first item */ |
242 | unsigned long Count = ReadVar (F); |
243 | |
244 | /* Read all the strings into C */ |
245 | while (Count--) { |
246 | CollAppend (C, ReadStr (F)); |
247 | } |
248 | } |
249 | |