]> git.sur5r.net Git - cc65/blobdiff - src/ar65/library.c
Merge remote-tracking branch 'upstream/master' into a5200
[cc65] / src / ar65 / library.c
index 94ae219c3652c4a7c85fb95399bc120b3e32628e..8d92a1ec600591ea3e394c33b329690881520d77 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                library.c                                 */
+/*                                 library.c                                 */
 /*                                                                           */
-/*        Library data structures and helpers for the ar65 archiver         */
+/*         Library data structures and helpers for the ar65 archiver         */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2000 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 1998-2013, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -38,9 +38,8 @@
 #include <errno.h>
 
 /* common */
-#include "bitops.h"
+#include "cmdline.h"
 #include "exprdefs.h"
-#include "filepos.h"
 #include "libdefs.h"
 #include "print.h"
 #include "symdefs.h"
 
 /* ar65 */
 #include "error.h"
-#include "global.h"
-#include "fileio.h"
-#include "objdata.h"
 #include "exports.h"
+#include "fileio.h"
+#include "global.h"
 #include "library.h"
+#include "objdata.h"
+#include "objfile.h"
 
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
+/* Name of the library file */
+const char*             LibName = 0;
+static char*            NewLibName = 0;
+
 /* File descriptor for the library file */
-FILE*                  NewLib = 0;
-static FILE*           Lib = 0;
-static const char*     LibName = 0;
+static FILE*            Lib = 0;
+static FILE*            NewLib = 0;
 
 /* The library header */
-static LibHeader               Header = {
+static LibHeader        Header = {
     LIB_MAGIC,
     LIB_VERSION,
-    0, 0
+    0,
+    0
 };
 
 
 
 /*****************************************************************************/
-/*                      Writing file data structures                        */
+/*                       Writing file data structures                        */
 /*****************************************************************************/
 
 
@@ -91,11 +95,11 @@ static void ReadHeader (void)
     /* Read the header fields, checking magic and version */
     Header.Magic   = Read32 (Lib);
     if (Header.Magic != LIB_MAGIC) {
-       Error ("`%s' is not a valid library file", LibName);
+        Error ("`%s' is not a valid library file", LibName);
     }
     Header.Version = Read16 (Lib);
     if (Header.Version != LIB_VERSION) {
-       Error ("Wrong data version in `%s'", LibName);
+        Error ("Wrong data version in `%s'", LibName);
     }
     Header.Flags   = Read16 (Lib);
     Header.IndexOffs = Read32 (Lib);
@@ -107,24 +111,14 @@ static void ReadIndexEntry (void)
 /* Read one entry in the index */
 {
     /* Create a new entry and insert it into the list */
-    ObjData* O         = NewObjData ();
+    ObjData* O  = NewObjData ();
 
     /* Module name/flags/MTime/Start/Size */
-    O->Name            = ReadStr (Lib);
-    O->Flags           = Read16 (Lib);
+    O->Name     = ReadStr (Lib);
+    O->Flags    = Read16 (Lib);
     O->MTime    = Read32 (Lib);
     O->Start    = Read32 (Lib);
     O->Size     = Read32 (Lib);
-
-    /* Exports */
-    O->ExportSize = Read16 (Lib);
-    O->Exports    = xmalloc (O->ExportSize);
-    ReadData (Lib, O->Exports, O->ExportSize);
-
-    /* Imports */
-    O->ImportSize = Read16 (Lib);
-    O->Imports    = xmalloc (O->ImportSize);
-    ReadData (Lib, O->Imports, O->ImportSize);
 }
 
 
@@ -132,24 +126,34 @@ static void ReadIndexEntry (void)
 static void ReadIndex (void)
 /* Read the index of a library file */
 {
-    unsigned Count;
+    unsigned Count, I;
 
     /* Seek to the start of the index */
     fseek (Lib, Header.IndexOffs, SEEK_SET);
 
     /* Read the object file count and calculate the cross ref size */
-    Count = Read16 (Lib);
+    Count = ReadVar (Lib);
 
     /* Read all entries in the index */
     while (Count--) {
-       ReadIndexEntry ();
+        ReadIndexEntry ();
+    }
+
+    /* Read basic object file data from the actual entries */
+    for (I = 0; I < CollCount (&ObjPool); ++I) {
+
+        /* Get the object file entry */
+        ObjData* O = CollAtUnchecked (&ObjPool, I);
+
+        /* Read data */
+        ObjReadData (Lib, O);
     }
 }
 
 
 
 /*****************************************************************************/
-/*                      Writing file data structures                        */
+/*                       Writing file data structures                        */
 /*****************************************************************************/
 
 
@@ -169,7 +173,7 @@ static void WriteHeader (void)
 
 
 
-static void WriteIndexEntry (ObjData* O)
+static void WriteIndexEntry (const ObjData* O)
 /* Write one index entry */
 {
     /* Module name/flags/MTime/start/size */
@@ -178,14 +182,6 @@ static void WriteIndexEntry (ObjData* O)
     Write32  (NewLib, O->MTime);
     Write32  (NewLib, O->Start);
     Write32  (NewLib, O->Size);
-
-    /* Exports */
-    Write16 (NewLib, O->ExportSize);
-    WriteData (NewLib, O->Exports, O->ExportSize);
-
-    /* Imports */
-    Write16 (NewLib, O->ImportSize);
-    WriteData (NewLib, O->Imports, O->ImportSize);
 }
 
 
@@ -193,7 +189,7 @@ static void WriteIndexEntry (ObjData* O)
 static void WriteIndex (void)
 /* Write the index of a library file */
 {
-    ObjData* O;
+    unsigned I;
 
     /* Sync I/O in case the last operation was a read */
     fseek (NewLib, 0, SEEK_CUR);
@@ -202,20 +198,18 @@ static void WriteIndex (void)
     Header.IndexOffs = ftell (NewLib);
 
     /* Write the object file count */
-    Write16 (NewLib, ObjCount);
+    WriteVar (NewLib, CollCount (&ObjPool));
 
     /* Write the object files */
-    O = ObjRoot;
-    while (O) {
-       WriteIndexEntry (O);
-               O = O->Next;
+    for (I = 0; I < CollCount (&ObjPool); ++I) {
+        WriteIndexEntry (CollConstAt (&ObjPool, I));
     }
 }
 
 
 
 /*****************************************************************************/
-/*                            High level stuff                              */
+/*                             High level stuff                              */
 /*****************************************************************************/
 
 
@@ -233,32 +227,40 @@ void LibOpen (const char* Name, int MustExist, int NeedTemp)
     Lib = fopen (Name, "rb");
     if (Lib == 0) {
 
-               /* File does not exist */
-               if (MustExist) {
-                   Error ("Library `%s' does not exist", Name);
-               } else {
-           Warning ("Library `%s' not found - will be created", Name);
-               }
+        /* File does not exist */
+        if (MustExist) {
+            Error ("Library `%s' does not exist", Name);
+        } else {
+            /* Announce the library's creation if ar65 is verbose. */
+            Print (stdout, 1,
+                   "%s: Library `%s' will be created.\n", ProgName, Name);
+        }
 
     } else {
 
         /* We have an existing file: Read the header */
-       ReadHeader ();
+        ReadHeader ();
 
-       /* Now read the existing index */
-               ReadIndex ();
+        /* Now read the existing index */
+        ReadIndex ();
 
     }
 
     if (NeedTemp) {
-       /* Create the temporary library */
-       NewLib = tmpfile ();
-       if (NewLib == 0) {
-           Error ("Cannot create temporary file: %s", strerror (errno));
-       }
-
-       /* Write a dummy header to the temp file */
-       WriteHeader ();
+
+        /* Create the temporary library name */
+        NewLibName = xmalloc (strlen (Name) + strlen (".temp") + 1);
+        strcpy (NewLibName, Name);
+        strcat (NewLibName, ".temp");
+
+        /* Create the temporary library */
+        NewLib = fopen (NewLibName, "w+b");
+        if (NewLib == 0) {
+            Error ("Cannot create temporary library file: %s", strerror (errno));
+        }
+
+        /* Write a dummy header to the temp file */
+        WriteHeader ();
     }
 }
 
@@ -276,10 +278,10 @@ unsigned long LibCopyTo (FILE* F, unsigned long Bytes)
 
     /* Copy loop */
     while (Bytes) {
-       unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
-       ReadData (F, Buf, Count);
-       WriteData (NewLib, Buf, Count);
-       Bytes -= Count;
+        unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
+        ReadData (F, Buf, Count);
+        WriteData (NewLib, Buf, Count);
+        Bytes -= Count;
     }
 
     /* Return the start position */
@@ -298,79 +300,11 @@ void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F)
 
     /* Copy loop */
     while (Bytes) {
-       unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
-       ReadData (Lib, Buf, Count);
-       WriteData (F, Buf, Count);
-       Bytes -= Count;
-    }
-}
-
-
-
-static unsigned long GetVar (unsigned char** Buf)
-/* Get a variable sized value from Buf */
-{
-    unsigned char C;
-    unsigned long V = 0;
-    unsigned Shift = 0;
-    do {
-       /* Read one byte */
-               C = **Buf;
-       ++(*Buf);
-       /* Add this char to the value */
-       V |= ((unsigned long)(C & 0x7F)) << Shift;
-       /* Next value */
-       Shift += 7;
-    } while (C & 0x80);
-
-    /* Return the result */
-    return V;
-}
-
-
-
-static void SkipExpr (unsigned char** Buf)
-/* Skip an expression in Buf */
-{
-    /* Get the operation and skip it */
-    unsigned char Op = **Buf;
-    ++(*Buf);
-
-    /* Filter leaf nodes */
-    switch (Op) {
-
-       case EXPR_NULL:
-           return;
-
-        case EXPR_LITERAL:
-           /* 32 bit literal value */
-           *Buf += 4;
-           return;
-
-        case EXPR_SYMBOL:
-           /* 16 bit symbol index */
-           *Buf += 2;
-           return;
-
-        case EXPR_SEGMENT:
-           /* 8 bit segment number */
-           *Buf += 1;
-           return;
+        unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes;
+        ReadData (Lib, Buf, Count);
+        WriteData (F, Buf, Count);
+        Bytes -= Count;
     }
-
-    /* What's left are unary and binary nodes */
-    SkipExpr (Buf);                    /* Skip left */
-    SkipExpr (Buf);            /* Skip right */
-}
-
-
-
-static void SkipFilePos (unsigned char** Buf)
-/* Skip a file position in Buf */
-{
-    (void) GetVar (Buf);       /* Line */
-    (void) GetVar (Buf);       /* Col */
-    (void) GetVar (Buf);       /* Name */
 }
 
 
@@ -380,51 +314,20 @@ static void LibCheckExports (ObjData* O)
  * checking for duplicates.
  */
 {
-    /* Get a pointer to the buffer */
-    unsigned char* Exports = O->Exports;
+    unsigned I;
 
-    /* Get the export count */
-    unsigned Count = GetVar (&Exports);
+    /* Let the user know what we do */
+    Print (stdout, 2, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports));
 
-    /* Read the exports */
-    Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, Count);
-    while (Count--) {
+    /* Insert the exports into the global table */
+    for (I = 0; I < CollCount (&O->Exports); ++I) {
+
+        /* Get the name of the export */
+        const char* Name = CollConstAt (&O->Exports, I);
 
-       unsigned char   Tag;
-       unsigned        Len;
-       char*           Name;
-
-       /* Get the export tag */
-       Tag = *Exports++;
-
-       /* condes decls may follow */
-       Exports += GET_EXP_CONDES_COUNT (Tag);
-
-               /* Next thing is name of symbol */
-       Len = GetVar (&Exports);
-       Name = xmalloc (Len + 1);
-       memcpy (Name, Exports, Len);
-       Name [Len] = '\0';
-       Exports += Len;
-
-       /* Skip value of symbol */
-       if (Tag & EXP_EXPR) {
-           /* Expression tree */
-           SkipExpr (&Exports);
-       } else {
-           /* Constant 32 bit value */
-           Exports += 4;
-       }
-
-       /* Skip the position */
-               SkipFilePos (&Exports);
-
-       /* Insert the name into the hash table */
-       Print (stdout, 1, "  %s\n", Name);
-       ExpInsert (Name, O->Index);
-
-       /* Free the name */
-       xfree (Name);
+        /* Insert the name into the hash table */
+        Print (stdout, 2, "  %s\n", Name);
+        ExpInsert (Name, O);
     }
 }
 
@@ -438,70 +341,67 @@ void LibClose (void)
     /* Do we have a temporary library? */
     if (NewLib) {
 
-       unsigned I;
-       unsigned char Buf [4096];
-       size_t Count;
-
-       /* Index the object files and make an array containing the objects */
-       MakeObjPool ();
+        unsigned I;
+        unsigned char Buf [4096];
+        size_t Count;
 
         /* Walk through the object file list, inserting exports into the
-        * export list checking for duplicates. Copy any data that is still
-        * in the old library into the new one.
-        */
-       for (I = 0; I < ObjCount; ++I) {
-
-           /* Get a pointer to the object */
-           ObjData* O = ObjPool [I];
-
-           /* Check exports, make global export table */
-           LibCheckExports (O);
-
-           /* Copy data if needed */
-           if ((O->Flags & OBJ_HAVEDATA) == 0) {
-               /* Data is still in the old library */
-               fseek (Lib, O->Start, SEEK_SET);
-               O->Start = ftell (NewLib);
-               LibCopyTo (Lib, O->Size);
-               O->Flags |= OBJ_HAVEDATA;
-           }
-       }
-
-       /* Write the index */
-       WriteIndex ();
-
-       /* Write the updated header */
-       WriteHeader ();
-
-       /* Close the file */
-       if (Lib && fclose (Lib) != 0) {
-           Error ("Error closing library: %s", strerror (errno));
-       }
-
-       /* Reopen the library and truncate it */
-       Lib = fopen (LibName, "wb");
-       if (Lib == 0) {
-           Error ("Cannot open library `%s' for writing: %s",
-                  LibName, strerror (errno));
-       }
-
-       /* Copy the new library to the new one */
-       fseek (NewLib, 0, SEEK_SET);
-       while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) {
-           if (fwrite (Buf, 1, Count, Lib) != Count) {
-               Error ("Cannot write to `%s': %s", LibName, strerror (errno));
-           }
-       }
+         * export list checking for duplicates. Copy any data that is still
+         * in the old library into the new one.
+         */
+        for (I = 0; I < CollCount (&ObjPool); ++I) {
+
+            /* Get a pointer to the object */
+            ObjData* O = CollAtUnchecked (&ObjPool, I);
+
+            /* Check exports, make global export table */
+            LibCheckExports (O);
+
+            /* Copy data if needed */
+            if ((O->Flags & OBJ_HAVEDATA) == 0) {
+                /* Data is still in the old library */
+                fseek (Lib, O->Start, SEEK_SET);
+                O->Start = ftell (NewLib);
+                LibCopyTo (Lib, O->Size);
+                O->Flags |= OBJ_HAVEDATA;
+            }
+        }
+
+        /* Write the index */
+        WriteIndex ();
+
+        /* Write the updated header */
+        WriteHeader ();
+
+        /* Close the file */
+        if (Lib && fclose (Lib) != 0) {
+            Error ("Error closing library: %s", strerror (errno));
+        }
+
+        /* Reopen the library and truncate it */
+        Lib = fopen (LibName, "wb");
+        if (Lib == 0) {
+            Error ("Cannot open library `%s' for writing: %s",
+                   LibName, strerror (errno));
+        }
+
+        /* Copy the temporary library to the new one */
+        fseek (NewLib, 0, SEEK_SET);
+        while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) {
+            if (fwrite (Buf, 1, Count, Lib) != Count) {
+                Error ("Cannot write to `%s': %s", LibName, strerror (errno));
+            }
+        }
     }
 
     /* Close both files */
     if (Lib && fclose (Lib) != 0) {
-       Error ("Problem closing `%s': %s", LibName, strerror (errno));
+        Error ("Problem closing `%s': %s", LibName, strerror (errno));
     }
     if (NewLib && fclose (NewLib) != 0) {
-       Error ("Problem closing temporary library file: %s", strerror (errno));
+        Error ("Problem closing temporary library file: %s", strerror (errno));
+    }
+    if (NewLibName && remove (NewLibName) != 0) {
+        Error ("Problem deleting temporary library file: %s", strerror (errno));
     }
 }
-
-
-