]> git.sur5r.net Git - cc65/blobdiff - src/ld65/fileio.c
Minor changes after review.
[cc65] / src / ld65 / fileio.c
index 263f3ab4845e49989ff643dc1c7a2ec9a465d0fd..f6a2719a67a3a2f386d79b19b68be4f54b4c6009 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                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 "mem.h"
 #include "fileio.h"
+#include "spool.h"
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
 
-void Write8 (FILE* F, unsigned char Val)
+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?)");
     }
 }
 
@@ -92,38 +119,55 @@ void WriteVal (FILE* F, unsigned long Val, unsigned Size)
 {
     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);
 
     }
 }
 
 
 
+void WriteVar (FILE* F, unsigned long V)
+/* 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.
+    */
+    do {
+        unsigned char C = (V & 0x7F);
+        V >>= 7;
+        if (V) {
+            C |= 0x80;
+        }
+        Write8 (F, C);
+    } while (V != 0);
+}
+
+
+
 void WriteStr (FILE* F, const char* S)
 /* Write a string to the file */
 {
     unsigned Len = strlen (S);
-    if (Len > 255) {
-               Internal ("String too long");
-    }
-    Write8 (F, (unsigned char) Len);
+    WriteVar (F, Len);
     WriteData (F, S, Len);
 }
 
@@ -133,7 +177,7 @@ void WriteData (FILE* F, const void* Data, unsigned Size)
 /* Write data to the file */
 {
     if (fwrite (Data, 1, Size, F) != Size) {
-       Error ("Write error (disk full?)");
+        Error ("Write error (disk full?)");
     }
 }
 
@@ -143,7 +187,7 @@ void WriteMult (FILE* F, unsigned char Val, unsigned long Count)
 /* Write one byte several times to the file */
 {
     while (Count--) {
-       Write8 (F, Val);
+        Write8 (F, Val);
     }
 }
 
@@ -154,7 +198,8 @@ unsigned Read8 (FILE* F)
 {
     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;
 }
@@ -199,8 +244,8 @@ long Read32Signed (FILE* F)
 
     /* Sign extend the value */
     if (V & 0x80000000UL) {
-       /* Signed value */
-       V |= ~0xFFFFFFFFUL;
+        /* Signed value */
+        V |= ~0xFFFFFFFFUL;
     }
 
     /* Return it as a long */
@@ -209,37 +254,56 @@ long Read32Signed (FILE* F)
 
 
 
-char* ReadStr (FILE* F, char* Str)
-/* Read a string from the file. Str must hold 256 chars at max */
+unsigned long ReadVar (FILE* F)
+/* Read a variable size value from the file */
 {
-    /* Read the length byte */
-    unsigned Len = Read8 (F);
-
-    /* Read the string itself */
-    ReadData (F, Str, Len);
-
-    /* Terminate the string and return it */
-    Str [Len] = '\0';
-    return Str;
+    /* 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.
+    */
+    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;
+    } while (C & 0x80);
+
+    /* Return the value read */
+    return V;
 }
 
 
 
-char* ReadMallocedStr (FILE* F)
-/* Read a string from the file into a malloced area */
+unsigned ReadStr (FILE* F)
+/* Read a string from the file, place it into the global string pool, and
+** return its string id.
+*/
 {
-    /* Read the length byte */
-    unsigned Len = Read8 (F);
+    unsigned    Id;
+    StrBuf      Buf = STATIC_STRBUF_INITIALIZER;
+
+    /* Read the length */
+    unsigned Len = ReadVar (F);
+
+    /* Expand the string buffer memory */
+    SB_Realloc (&Buf, Len);
+
+    /* Read the string */
+    ReadData (F, SB_GetBuf (&Buf), Len);
+    Buf.Len = Len;
 
-    /* Allocate memory */
-    char* Str = Xmalloc (Len + 1);
+    /* Insert it into the string pool and remember the id */
+    Id = GetStrBufId (&Buf);
 
-    /* Read the string itself */
-    ReadData (F, Str, Len);
+    /* Free the memory buffer */
+    SB_Done (&Buf);
 
-    /* Terminate the string and return it */
-    Str [Len] = '\0';
-    return Str;
+    /* Return the string id */
+    return Id;
 }
 
 
@@ -247,10 +311,10 @@ char* ReadMallocedStr (FILE* F)
 FilePos* ReadFilePos (FILE* F, FilePos* Pos)
 /* Read a file position from the file */
 {
-    /* The line number is encoded as 24 bit value to save some space */
-    Pos->Line =        Read24 (F);
-    Pos->Col  = Read8 (F);
-    Pos->Name = Read8 (F);
+    /* Read the data fields */
+    Pos->Line = ReadVar (F);
+    Pos->Col  = ReadVar (F);
+    Pos->Name = ReadVar (F);
     return Pos;
 }
 
@@ -259,11 +323,12 @@ FilePos* ReadFilePos (FILE* F, FilePos* 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;
 }
-
-
-