/*****************************************************************************/
/* */
-/* library.c */
+/* library.c */
/* */
-/* Library data structures and helpers for the ar65 archiver */
+/* Library data structures and helpers for the ar65 archiver */
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (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 */
#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,
/*****************************************************************************/
-/* Writing file data structures */
+/* Writing file data structures */
/*****************************************************************************/
/* 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);
static void ReadIndexEntry (void)
/* Read one entry in the index */
{
- unsigned I;
-
/* 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);
-
- /* Strings */
- O->StringCount = ReadVar (Lib);
- O->Strings = xmalloc (O->StringCount * sizeof (char*));
- for (I = 0; I < O->StringCount; ++I) {
- O->Strings[I] = ReadStr (Lib);
- }
-
- /* Exports */
- O->ExportSize = ReadVar (Lib);
- O->Exports = xmalloc (O->ExportSize);
- ReadData (Lib, O->Exports, O->ExportSize);
-
- /* Imports */
- O->ImportSize = ReadVar (Lib);
- O->Imports = xmalloc (O->ImportSize);
- ReadData (Lib, O->Imports, O->ImportSize);
}
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 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 */
/*****************************************************************************/
-static void WriteIndexEntry (ObjData* O)
+static void WriteIndexEntry (const ObjData* O)
/* Write one index entry */
{
- unsigned I;
-
/* Module name/flags/MTime/start/size */
WriteStr (NewLib, O->Name);
Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA);
Write32 (NewLib, O->MTime);
Write32 (NewLib, O->Start);
Write32 (NewLib, O->Size);
-
- /* Strings */
- WriteVar (NewLib, O->StringCount);
- for (I = 0; I < O->StringCount; ++I) {
- WriteStr (NewLib, O->Strings[I]);
- }
-
- /* Exports */
- WriteVar (NewLib, O->ExportSize);
- WriteData (NewLib, O->Exports, O->ExportSize);
-
- /* Imports */
- WriteVar (NewLib, O->ImportSize);
- WriteData (NewLib, O->Imports, O->ImportSize);
}
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);
Header.IndexOffs = ftell (NewLib);
/* Write the object file count */
- WriteVar (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 */
/*****************************************************************************/
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 ();
}
}
/* 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 */
/* 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:
- /* Variable seized symbol index */
- (void) GetVar (Buf);
- return;
-
- case EXPR_SECTION:
- /* 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 */
}
* checking for duplicates.
*/
{
- /* Get a pointer to the buffer */
- unsigned char* Exports = O->Exports;
-
- /* Get the export count */
- unsigned Count = GetVar (&Exports);
-
- /* Read the exports */
- Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, Count);
- while (Count--) {
-
- unsigned char Tag;
- const char* Name;
-
- /* Get the export tag */
- Tag = *Exports++;
-
- /* condes decls may follow */
- Exports += GET_EXP_CONDES_COUNT (Tag);
+ unsigned I;
- /* Next thing is index of name of symbol */
- Name = GetObjString (O, GetVar (&Exports));
+ /* Let the user know what we do */
+ Print (stdout, 2, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports));
- /* Skip value of symbol */
- if (Tag & EXP_EXPR) {
- /* Expression tree */
- SkipExpr (&Exports);
- } else {
- /* Constant 32 bit value */
- Exports += 4;
- }
+ /* Insert the exports into the global table */
+ for (I = 0; I < CollCount (&O->Exports); ++I) {
- /* Skip the position */
- SkipFilePos (&Exports);
+ /* Get the name of the export */
+ const char* Name = CollConstAt (&O->Exports, I);
- /* Insert the name into the hash table */
- Print (stdout, 1, " %s\n", Name);
- ExpInsert (Name, O->Index);
+ /* Insert the name into the hash table */
+ Print (stdout, 2, " %s\n", Name);
+ ExpInsert (Name, O);
}
}
/* 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));
}
}
-
-
-