static unsigned ExpCount = 0; /* Export count */
static Export** ExpPool = 0; /* Exports array */
+/* Defines for the flags in Import */
+#define IMP_INLIST 0x0001U /* Import is in exports list */
+
/* Defines for the flags in Export */
-#define EXP_USERMARK 0x0001
+#define EXP_INLIST 0x0001U /* Export is in exports list */
+#define EXP_USERMARK 0x0002U /* User setable flag */
I->Obj = Obj;
I->Exp = 0;
I->Name = INVALID_STRING_ID;
+ I->Flags = 0;
I->Type = Type;
/* Return the new structure */
/* This is a dummy export */
++ImpOpen;
}
+
+ /* Mark the import so we know it's in the list */
+ I->Flags |= IMP_INLIST;
+}
+
+
+
+void FreeImport (Import* I)
+/* Free an import. NOTE: This won't remove the import from the exports table,
+ * so it may only be called for unused imports (imports from modules that
+ * aren't referenced).
+ */
+{
+ /* Safety */
+ PRECONDITION ((I->Flags & IMP_INLIST) == 0);
+
+ /* Free the struct */
+ xfree (I);
}
+void FreeExport (Export* E)
+/* Free an export. NOTE: This won't remove the export from the exports table,
+ * so it may only be called for unused exports (exports from modules that
+ * aren't referenced).
+ */
+{
+ /* Safety */
+ PRECONDITION ((E->Flags & EXP_INLIST) == 0);
+
+ /* Free the export expression */
+ FreeExpr (E->Expr);
+
+ /* Free the struct */
+ xfree (E);
+}
+
+
+
void InsertExport (Export* E)
/* Insert an exported identifier and check if it's already in the list */
{
Import* Imp;
unsigned Hash;
+ /* Mark the export as inserted */
+ E->Flags |= EXP_INLIST;
+
/* Insert the export into any condes tables if needed */
if (IS_EXP_CONDES (E->Type)) {
ConDesAddExport (E);
Last = 0;
L = HashTab[Hash];
do {
- if (L->Name == E->Name) {
+ if (L->Name == E->Name) {
/* This may be an unresolved external */
if (L->Expr == 0) {
- /* This *is* an unresolved external */
+ /* This *is* an unresolved external. Use the actual export
+ * in E instead of the dummy one in L.
+ */
E->Next = L->Next;
E->ImpCount = L->ImpCount;
E->ImpList = L->ImpList;
- if (Last) {
- Last->Next = E;
- } else {
+ if (Last) {
+ Last->Next = E;
+ } else {
HashTab[Hash] = E;
- }
+ }
ImpOpen -= E->ImpCount; /* Decrease open imports now */
- xfree (L);
- /* We must run through the import list and change the
+ xfree (L);
+ /* We must run through the import list and change the
* export pointer now.
- */
- Imp = E->ImpList;
- while (Imp) {
- Imp->Exp = E;
- Imp = Imp->Next;
- }
- } else {
- /* Duplicate entry, ignore it */
- Warning ("Duplicate external identifier: `%s'",
+ */
+ Imp = E->ImpList;
+ while (Imp) {
+ Imp->Exp = E;
+ Imp = Imp->Next;
+ }
+ } else {
+ /* Duplicate entry, ignore it */
+ Warning ("Duplicate external identifier: `%s'",
GetString (L->Name));
- }
- return;
+ }
+ return;
}
Last = L;
L = L->Next;
/* User defined export */
Warning ("Type mismatch for `%s', export in "
"%s(%lu), import in %s(%lu)",
- GetString (E->Name),
+ GetString (E->Name),
GetSourceFileName (E->Obj, Imp->Pos.Name),
- E->Pos.Line,
+ E->Pos.Line,
GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
} else {
/* Export created by the linker */
Warning ("Type mismatch for `%s', imported from %s(%lu)",
- GetString (E->Name),
+ GetString (E->Name),
GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
}
static int CmpExpName (const void* K1, const void* K2)
/* Compare function for qsort */
{
- return strcmp (GetString ((*(Export**)K1)->Name),
+ return strcmp (GetString ((*(Export**)K1)->Name),
GetString ((*(Export**)K2)->Name));
}
/* Print an error about a circular reference using to define the given export */
{
Error ("Circular reference for symbol `%s', %s(%lu)",
- GetString (E->Name),
+ GetString (E->Name),
GetSourceFileName (E->Obj, E->Pos.Name),
E->Pos.Line);
}
-
+
FilePos Pos; /* File position of reference */
struct Export* Exp; /* Matching export for this import */
unsigned Name; /* Name if not in table */
+ unsigned char Flags; /* Generic flags */
unsigned char Type; /* Type of import */
};
+void FreeImport (Import* I);
+/* Free an import. NOTE: This won't remove the import from the exports table,
+ * so it may only be called for unused imports (imports from modules that
+ * aren't referenced).
+ */
+
Import* ReadImport (FILE* F, ObjData* Obj);
/* Read an import from a file and insert it into the table */
void InsertImport (Import* I);
/* Insert an import into the table */
+void FreeExport (Export* E);
+/* Free an export. NOTE: This won't remove the export from the exports table,
+ * so it may only be called for unused exports (exports from modules that
+ * aren't referenced).
+ */
+
Export* ReadExport (FILE* F, ObjData* Obj);
/* Read an export from a file */
#include "error.h"
#include "exports.h"
#include "fileio.h"
+#include "library.h"
#include "objdata.h"
#include "objfile.h"
-#include "library.h"
+#include "spool.h"
/* Library data */
static FILE* Lib = 0;
-static char* LibName = 0;
static unsigned ModuleCount = 0;
static ObjData** Index = 0;
/*****************************************************************************/
-/* Reading file data structures */
+/* Reading file data structures */
/*****************************************************************************/
-static void LibReadObjHeader (ObjData* O)
+static void LibReadObjHeader (ObjData* O, const char* LibName)
/* Read the header of the object file checking the signature */
{
O->Header.Magic = Read32 (Lib);
/* Create a new entry and insert it into the list */
ObjData* O = NewObjData ();
- /* Module name/flags/MTime/Start/Size */
- O->Name = ReadStr (Lib);
+ /* Module name */
+ char* Name = ReadStr (Lib);
+ O->Name = GetStringId (Name);
+ xfree (Name);
+
+ /* Module flags/MTime/Start/Size */
O->Flags = Read16 (Lib);
- Read32 (Lib); /* Skip MTime */
+ O->MTime = Read32 (Lib);
O->Start = Read32 (Lib);
Read32 (Lib); /* Skip Size */
* be satisfied.
*/
{
- int Add;
+ unsigned LibName;
+ int HaveAdditions;
unsigned I;
LibHeader Header;
/* Store the parameters, so they're visible for other routines */
Lib = F;
- LibName = xstrdup (Name);
+ LibName = GetStringId (Name);
/* Read the remaining header fields (magic is already read) */
Header.Magic = LIB_MAGIC;
* were added.
*/
do {
- Add = 0;
- for (I = 0; I < ModuleCount; ++I) {
- ObjData* O = Index [I];
- if ((O->Flags & OBJ_REF) == 0) {
- LibCheckExports (O);
- if (O->Flags & OBJ_REF) {
- /* The routine added the file */
- Add = 1;
- }
- }
- }
- } while (Add);
+ HaveAdditions = 0;
+ for (I = 0; I < ModuleCount; ++I) {
+ ObjData* O = Index [I];
+ if ((O->Flags & OBJ_REF) == 0) {
+ LibCheckExports (O);
+ if (O->Flags & OBJ_REF) {
+ /* The routine added the file */
+ HaveAdditions = 1;
+ }
+ }
+ }
+ } while (HaveAdditions);
/* Add the files list and sections for all requested modules */
for (I = 0; I < ModuleCount; ++I) {
+
+ /* Get the object data */
ObjData* O = Index [I];
+
+ /* Is this object file referenced? */
if (O->Flags & OBJ_REF) {
/* Seek to the start of the object file and read the header */
fseek (Lib, O->Start, SEEK_SET);
- LibReadObjHeader (O);
+ LibReadObjHeader (O, Name);
/* Seek to the start of the files list and read the files list */
fseek (Lib, O->Start + O->Header.FileOffs, SEEK_SET);
fseek (Lib, O->Start + O->Header.SegOffs, SEEK_SET);
ObjReadSections (Lib, O);
- /* We have the data now */
- O->Flags |= OBJ_HAVEDATA;
- }
+ /* Add a pointer to the library name */
+ O->LibName = LibName;
+
+ /* All references to strings are now resolved, so we can delete
+ * the module string pool.
+ */
+ FreeObjStrings (O);
+
+ /* Insert the object into the list of all used object files */
+ InsertObjData (O);
+
+ } else {
- /* All references to strings are now resolved, so we can delete
- * the module string pool.
- */
- FreeObjStrings (O);
+ /* Unreferenced object file, remove it */
+ FreeObjData (O);
- /* Add a pointer to the library name */
- O->LibName = LibName;
+ }
}
/* Done. Close the file, release allocated memory */
fclose (F);
xfree (Index);
Lib = 0;
- LibName = 0;
ModuleCount = 0;
Index = 0;
}
void CreateMapFile (void)
/* Create a map file */
{
- ObjData* O;
unsigned I;
/* Open the map file */
/* Write a modules list */
fprintf (F, "Modules list:\n"
"-------------\n");
- O = ObjRoot;
- while (O) {
- if (O->Flags & OBJ_HAVEDATA) {
- /* We've linked this module */
- if (O->LibName) {
- /* The file is from a library */
- fprintf (F, "%s(%s):\n", O->LibName, GetObjFileName (O));
- } else {
- fprintf (F, "%s:\n", GetObjFileName (O));
- }
- for (I = 0; I < O->SectionCount; ++I) {
- const Section* S = O->Sections [I];
- /* Don't include zero sized sections if not explicitly
- * requested
- */
- if (VerboseMap || S->Size > 0) {
- fprintf (F, " %-15s Offs = %06lX Size = %06lX\n",
- GetString (S->Seg->Name), S->Offs, S->Size);
- }
- }
- }
- O = O->Next;
+ for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+ unsigned J;
+
+ /* Get the object file */
+ const ObjData* O = CollConstAt (&ObjDataList, I);
+
+ /* Output the data */
+ if (O->LibName != INVALID_STRING_ID) {
+ /* The file is from a library */
+ fprintf (F, "%s(%s):\n", GetString (O->LibName), GetObjFileName (O));
+ } else {
+ fprintf (F, "%s:\n", GetObjFileName (O));
+ }
+ for (J = 0; J < O->SectionCount; ++J) {
+ const Section* S = O->Sections [J];
+ /* Don't include zero sized sections if not explicitly
+ * requested
+ */
+ if (VerboseMap || S->Size > 0) {
+ fprintf (F, " %-15s Offs = %06lX Size = %06lX\n",
+ GetString (S->Seg->Name), S->Offs, S->Size);
+ }
+ }
}
/* Write the segment list */
void CreateLabelFile (void)
/* Create a label file */
{
- ObjData* O;
+ unsigned I;
/* Open the label file */
FILE* F = fopen (LabelFileName, "w");
/* Print the labels for the export symbols */
PrintExportLabels (F);
- /* Print debug symbols from all modules we have linked into the output file */
- O = ObjRoot;
- while (O) {
- if (O->Flags & OBJ_HAVEDATA) {
- /* We've linked this module */
- PrintDbgSymLabels (O, F);
+ /* Create labels from all modules we have linked into the output file */
+ for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+ /* Get the object file */
+ ObjData* O = CollAtUnchecked (&ObjDataList, I);
- }
- O = O->Next;
+ /* Output the labels */
+ PrintDbgSymLabels (O, F);
}
/* If we should mark write protected areas as such, do it */
void CreateDbgFile (void)
/* Create a debug info file */
{
- ObjData* O;
+ unsigned I;
/* Open the debug info file */
FILE* F = fopen (DbgFileName, "w");
}
/* Print line infos from all modules we have linked into the output file */
- O = ObjRoot;
- while (O) {
- if (O->Flags & OBJ_HAVEDATA) {
- /* We've linked this module */
- PrintDbgInfo (O, F);
-
- }
- O = O->Next;
+ for (I = 0; I < CollCount (&ObjDataList); ++I) {
+
+ /* Get the object file */
+ ObjData* O = CollAtUnchecked (&ObjDataList, I);
+
+ /* Output debug info */
+ PrintDbgInfo (O, F);
}
/* Close the file */
/* ld65 */
#include "error.h"
+#include "exports.h"
#include "fileinfo.h"
#include "objdata.h"
#include "spool.h"
-/* Object data list management */
-unsigned ObjCount = 0; /* Count of object files in the list */
-ObjData* ObjRoot = 0; /* List of object files */
-ObjData* ObjLast = 0; /* Last entry in list */
-ObjData** ObjPool = 0; /* Object files as array */
+/* Collection containing used ObjData objects */
+Collection ObjDataList = STATIC_COLLECTION_INITIALIZER;
/* Initialize the data */
O->Next = 0;
- O->Name = 0;
- O->LibName = 0;
+ O->Name = INVALID_STRING_ID;
+ O->LibName = INVALID_STRING_ID;
+ O->MTime = 0;
O->Flags = 0;
O->Start = 0;
O->ExportCount = 0;
O->StringCount = 0;
O->Strings = 0;
- /* Link it into the list */
- if (ObjLast) {
- ObjLast->Next = O;
- ObjLast = O;
- } else {
- /* First entry */
- ObjRoot = ObjLast = O;
- }
-
- /* One object file more now */
- ++ObjCount;
-
/* Return the new entry */
return O;
}
+void FreeObjData (ObjData* O)
+/* Free an ObjData object. NOTE: This function works only for unused object
+ * data, that is, ObjData objects that aren't used because they aren't
+ * referenced.
+ */
+{
+ /* Unused ObjData do only have the string pool, Exports and Imports. */
+ while (O->ExportCount) {
+ FreeExport (O->Exports[--O->ExportCount]);
+ }
+ xfree (O->Exports);
+ while (O->ImportCount) {
+ FreeImport (O->Imports[--O->ImportCount]);
+ }
+ xfree (O->Imports);
+ FreeObjStrings (O);
+ xfree (O);
+}
+
+
+
void FreeObjStrings (ObjData* O)
/* Free the module string data. Used once the object file is loaded completely
* when all strings are converted to global strings.
+void InsertObjData (ObjData* O)
+/* Insert the ObjData object into the collection of used ObjData objects. */
+{
+ CollAppend (&ObjDataList, O);
+}
+
+
+
const char* GetObjString (const ObjData* O, unsigned Index)
/* Get a string from the object file string table. Abort if the string index
* is invalid.
* file is NULL.
*/
{
- return O? O->Name : "[linker generated]";
+ return O? GetString (O->Name) : "[linker generated]";
}
/* common */
+#include "coll.h"
#include "objdefs.h"
/* Values for the Flags field */
#define OBJ_REF 0x0001 /* We have a reference to this file */
-#define OBJ_HAVEDATA 0x0002 /* We have this object file already */
-#define OBJ_MARKED 0x0004 /* Generic marker bit */
-
/* Internal structure holding object file data */
typedef struct ObjData ObjData;
struct ObjData {
- ObjData* Next; /* Linked list of all objects */
- char* Name; /* Module name */
- char* LibName; /* Name of library */
+ ObjData* Next; /* Linked list of all objects */
+ unsigned Name; /* Module name */
+ unsigned LibName; /* Name of library */
+ unsigned long MTime; /* Time of last modification */
ObjHeader Header; /* Header of file */
unsigned long Start; /* Start offset of data in library */
unsigned Flags;
-/* Object data list management */
-extern unsigned ObjCount; /* Count of files in the list */
-extern ObjData* ObjRoot; /* List of object files */
-extern ObjData* ObjLast; /* Last entry in list */
+/* Collection containing used ObjData objects */
+extern Collection ObjDataList;
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
ObjData* NewObjData (void);
/* Allocate a new structure on the heap, insert it into the list, return it */
+void FreeObjData (ObjData* O);
+/* Free an ObjData object. NOTE: This function works only for unused object
+ * data, that is, ObjData objects that aren't used because they aren't
+ * referenced.
+ */
+
void FreeObjStrings (ObjData* O);
/* Free the module string data. Used once the object file is loaded completely
* when all strings are converted to global strings.
*/
+void InsertObjData (ObjData* O);
+/* Insert the ObjData object into the collection of used ObjData objects. */
+
const char* GetObjString (const ObjData* O, unsigned Index);
/* Get a string from the object file string table. Abort if the string index
* is invalid.
#include "fileio.h"
#include "lineinfo.h"
#include "objdata.h"
-#include "segments.h"
#include "objfile.h"
+#include "segments.h"
+#include "spool.h"
-static const char* GetModule (const char* Name)
-/* Get a module name from the file name */
+static unsigned GetModule (const char* Name)
+/* Get a module name index from the file name */
{
/* Make a module name from the file name */
const char* Module = FindName (Name);
if (*Module == 0) {
Error ("Cannot make module name from `%s'", Name);
}
- return Module;
+ return GetStringId (Module);
}
ObjReadHeader (Obj, &O->Header, Name);
/* Initialize the object module data structure */
- O->Name = xstrdup (GetModule (Name));
- O->Flags = OBJ_HAVEDATA;
+ O->Name = GetModule (Name);
/* Read the string pool from the object file */
fseek (Obj, O->Header.StrPoolOffs, SEEK_SET);
ObjReadSections (Obj, O);
/* Mark this object file as needed */
- O->Flags |= OBJ_REF | OBJ_HAVEDATA;
+ O->Flags |= OBJ_REF;
/* Done, close the file (we read it only, so no error check) */
fclose (Obj);
* string pool.
*/
FreeObjStrings (O);
+
+ /* Insert the object into the list of all used object files */
+ InsertObjData (O);
}