1 /*****************************************************************************/
5 /* File I/O for the ld65 linker */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 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 void Write8 (FILE* F, unsigned Val)
55 /* Write an 8 bit value to the file */
57 if (putc (Val, F) == EOF) {
58 Error ("Write error (disk full?)");
64 void Write16 (FILE* F, unsigned Val)
65 /* Write a 16 bit value to the file */
67 Write8 (F, (unsigned char) Val);
68 Write8 (F, (unsigned char) (Val >> 8));
73 void Write24 (FILE* F, unsigned long Val)
74 /* Write a 24 bit value to the file */
76 Write8 (F, (unsigned char) Val);
77 Write8 (F, (unsigned char) (Val >> 8));
78 Write8 (F, (unsigned char) (Val >> 16));
83 void Write32 (FILE* F, unsigned long Val)
84 /* Write a 32 bit value to the file */
86 Write8 (F, (unsigned char) Val);
87 Write8 (F, (unsigned char) (Val >> 8));
88 Write8 (F, (unsigned char) (Val >> 16));
89 Write8 (F, (unsigned char) (Val >> 24));
94 void WriteVal (FILE* F, unsigned long Val, unsigned Size)
95 /* Write a value of the given size to the output file */
116 Internal ("WriteVal: Invalid size: %u", Size);
123 void WriteVar (FILE* F, unsigned long V)
124 /* Write a variable sized value to the file in special encoding */
126 /* We will write the value to the file in 7 bit chunks. If the 8th bit
127 * is clear, we're done, if it is set, another chunk follows. This will
128 * allow us to encode smaller values with less bytes, at the expense of
129 * needing 5 bytes if a 32 bit value is written to file.
132 unsigned char C = (V & 0x7F);
143 void WriteStr (FILE* F, const char* S)
144 /* Write a string to the file */
146 unsigned Len = strlen (S);
148 WriteData (F, S, Len);
153 void WriteData (FILE* F, const void* Data, unsigned Size)
154 /* Write data to the file */
156 if (fwrite (Data, 1, Size, F) != Size) {
157 Error ("Write error (disk full?)");
163 void WriteMult (FILE* F, unsigned char Val, unsigned long Count)
164 /* Write one byte several times to the file */
173 unsigned Read8 (FILE* F)
174 /* Read an 8 bit value from the file */
178 Error ("Read error (file corrupt?)");
185 unsigned Read16 (FILE* F)
186 /* Read a 16 bit value from the file */
188 unsigned Lo = Read8 (F);
189 unsigned Hi = Read8 (F);
190 return (Hi << 8) | Lo;
195 unsigned long Read24 (FILE* F)
196 /* Read a 24 bit value from the file */
198 unsigned long Lo = Read16 (F);
199 unsigned long Hi = Read8 (F);
200 return (Hi << 16) | Lo;
205 unsigned long Read32 (FILE* F)
206 /* Read a 32 bit value from the file */
208 unsigned long Lo = Read16 (F);
209 unsigned long Hi = Read16 (F);
210 return (Hi << 16) | Lo;
215 long Read32Signed (FILE* F)
216 /* Read a 32 bit value from the file. Sign extend the value. */
218 /* Read a 32 bit value */
219 unsigned long V = Read32 (F);
221 /* Sign extend the value */
222 if (V & 0x80000000UL) {
227 /* Return it as a long */
233 unsigned long ReadVar (FILE* F)
234 /* Read a variable size value from the file */
236 /* The value was written to the file in 7 bit chunks LSB first. If there
237 * are more bytes, bit 8 is set, otherwise it is clear.
245 /* Encode it into the target value */
246 V |= ((unsigned long)(C & 0x7F)) << Shift;
251 /* Return the value read */
257 unsigned ReadStr (FILE* F)
258 /* Read a string from the file, place it into the global string pool, and
259 * return its string id.
266 /* Read the length */
267 unsigned Len = ReadVar (F);
269 /* If the string is short enough, use our buffer on the stack, otherwise
270 * allocate space on the heap.
272 if (Len < sizeof (Buf)) {
275 B = xmalloc (Len + 1);
278 /* Read the string */
279 ReadData (F, B, Len);
281 /* Terminate the string */
284 /* Insert it into the string pool and remember the id */
285 Id = GetStringId (B);
287 /* If we had allocated memory before, free it now */
292 /* Return the string id */
298 FilePos* ReadFilePos (FILE* F, FilePos* Pos)
299 /* Read a file position from the file */
301 /* Read the data fields */
302 Pos->Line = ReadVar (F);
303 Pos->Col = ReadVar (F);
304 Pos->Name = ReadVar (F);
310 void* ReadData (FILE* F, void* Data, unsigned Size)
311 /* Read data from the file */
313 /* Explicitly allow reading zero bytes */
315 if (fread (Data, 1, Size, F) != Size) {
316 Error ("Read error (file corrupt?)");