/*****************************************************************************/
/* */
-/* fileio.c */
+/* fileio.c */
/* */
-/* File I/O for the ld65 linker */
+/* File I/O for the ld65 linker */
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <string.h>
+#include <errno.h>
/* common */
#include "xmalloc.h"
/* ld65 */
#include "error.h"
#include "fileio.h"
+#include "spool.h"
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
+void FileSetPos (FILE* F, unsigned long Pos)
+/* Seek to the given absolute position, fail on errors */
+{
+ if (fseek (F, Pos, SEEK_SET) != 0) {
+ Error ("Cannot seek: %s", strerror (errno));
+ }
+}
+
+
+
+unsigned long FileGetPos (FILE* F)
+/* Return the current file position, fail on errors */
+{
+ long Pos = ftell (F);
+ if (Pos < 0) {
+ Error ("Error in ftell: %s", strerror (errno));
+ }
+ return Pos;
+}
+
+
+
void Write8 (FILE* F, unsigned Val)
/* Write an 8 bit value to the file */
{
if (putc (Val, F) == EOF) {
- Error ("Write error (disk full?)");
+ Error ("Write error (disk full?)");
}
}
{
switch (Size) {
- case 1:
- Write8 (F, Val);
- break;
+ case 1:
+ Write8 (F, Val);
+ break;
- case 2:
- Write16 (F, Val);
- break;
+ case 2:
+ Write16 (F, Val);
+ break;
- case 3:
- Write24 (F, Val);
- break;
+ case 3:
+ Write24 (F, Val);
+ break;
- case 4:
- Write32 (F, Val);
- break;
+ case 4:
+ Write32 (F, Val);
+ break;
- default:
- Internal ("WriteVal: Invalid size: %u", Size);
+ default:
+ Internal ("WriteVal: Invalid size: %u", Size);
}
}
/* Write a variable sized value to the file in special encoding */
{
/* We will write the value to the file in 7 bit chunks. If the 8th bit
- * is clear, we're done, if it is set, another chunk follows. This will
- * allow us to encode smaller values with less bytes, at the expense of
- * needing 5 bytes if a 32 bit value is written to file.
- */
+ ** is clear, we're done, if it is set, another chunk follows. This will
+ ** allow us to encode smaller values with less bytes, at the expense of
+ ** needing 5 bytes if a 32 bit value is written to file.
+ */
do {
- unsigned char C = (V & 0x7F);
- V >>= 7;
- if (V) {
- C |= 0x80;
- }
- Write8 (F, C);
+ unsigned char C = (V & 0x7F);
+ V >>= 7;
+ if (V) {
+ C |= 0x80;
+ }
+ Write8 (F, C);
} while (V != 0);
}
/* Write data to the file */
{
if (fwrite (Data, 1, Size, F) != Size) {
- Error ("Write error (disk full?)");
+ Error ("Write error (disk full?)");
}
}
/* Write one byte several times to the file */
{
while (Count--) {
- Write8 (F, Val);
+ Write8 (F, Val);
}
}
{
int C = getc (F);
if (C == EOF) {
- Error ("Read error (file corrupt?)");
+ long Pos = ftell (F);
+ Error ("Read error at position %ld (file corrupt?)", Pos);
}
return C;
}
/* Sign extend the value */
if (V & 0x80000000UL) {
- /* Signed value */
- V |= ~0xFFFFFFFFUL;
+ /* Signed value */
+ V |= ~0xFFFFFFFFUL;
}
/* Return it as a long */
/* Read a variable size value from the file */
{
/* The value was written to the file in 7 bit chunks LSB first. If there
- * are more bytes, bit 8 is set, otherwise it is clear.
- */
+ ** are more bytes, bit 8 is set, otherwise it is clear.
+ */
unsigned char C;
unsigned long V = 0;
unsigned Shift = 0;
do {
- /* Read one byte */
- C = Read8 (F);
- /* Encode it into the target value */
- V |= ((unsigned long)(C & 0x7F)) << Shift;
- /* Next value */
- Shift += 7;
+ /* Read one byte */
+ C = Read8 (F);
+ /* Encode it into the target value */
+ V |= ((unsigned long)(C & 0x7F)) << Shift;
+ /* Next value */
+ Shift += 7;
} while (C & 0x80);
/* Return the value read */
-char* ReadStr (FILE* F)
-/* Read a string from the file (the memory will be malloc'ed) */
+unsigned ReadStr (FILE* F)
+/* Read a string from the file, place it into the global string pool, and
+** return its string id.
+*/
{
+ unsigned Id;
+ StrBuf Buf = STATIC_STRBUF_INITIALIZER;
+
/* Read the length */
unsigned Len = ReadVar (F);
- /* Allocate memory and read the string itself */
- char* S = xmalloc (Len + 1);
- ReadData (F, S, Len);
+ /* Expand the string buffer memory */
+ SB_Realloc (&Buf, Len);
+
+ /* Read the string */
+ ReadData (F, SB_GetBuf (&Buf), Len);
+ Buf.Len = Len;
+
+ /* Insert it into the string pool and remember the id */
+ Id = GetStrBufId (&Buf);
- /* Terminate the string and return it */
- S [Len] = '\0';
- return S;
+ /* Free the memory buffer */
+ SB_Done (&Buf);
+
+ /* Return the string id */
+ return Id;
}
/* Read a file position from the file */
{
/* Read the data fields */
- Pos->Line = ReadVar (F);
+ Pos->Line = ReadVar (F);
Pos->Col = ReadVar (F);
Pos->Name = ReadVar (F);
return Pos;
void* ReadData (FILE* F, void* Data, unsigned Size)
/* Read data from the file */
{
- if (fread (Data, 1, Size, F) != Size) {
- Error ("Read error (file corrupt?)");
+ /* Explicitly allow reading zero bytes */
+ if (Size > 0) {
+ if (fread (Data, 1, Size, F) != Size) {
+ long Pos = ftell (F);
+ Error ("Read error at position %ld (file corrupt?)", Pos);
+ }
}
return Data;
}
-
-
-
-