/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "hashstr.h"
#include "xmalloc.h"
-
+
/* ar65 */
#include "error.h"
#include "objdata.h"
/* A hash table entry */
-typedef struct HashEntry_ HashEntry;
-struct HashEntry_ {
+typedef struct HashEntry HashEntry;
+struct HashEntry {
HashEntry* Next; /* Next in list */
unsigned Module; /* Module index */
char Name [1]; /* Name of identifier */
-
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
static LibHeader Header = {
LIB_MAGIC,
LIB_VERSION,
- 0, 0
+ 0,
+ 0
};
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 ();
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 = Read16 (Lib);
+ O->ExportSize = ReadVar (Lib);
O->Exports = xmalloc (O->ExportSize);
ReadData (Lib, O->Exports, O->ExportSize);
/* Imports */
- O->ImportSize = Read16 (Lib);
+ O->ImportSize = ReadVar (Lib);
O->Imports = xmalloc (O->ImportSize);
ReadData (Lib, O->Imports, O->ImportSize);
}
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--) {
static void WriteIndexEntry (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->Start);
Write32 (NewLib, O->Size);
+ /* Strings */
+ WriteVar (NewLib, O->StringCount);
+ for (I = 0; I < O->StringCount; ++I) {
+ WriteStr (NewLib, O->Strings[I]);
+ }
+
/* Exports */
- Write16 (NewLib, O->ExportSize);
+ WriteVar (NewLib, O->ExportSize);
WriteData (NewLib, O->Exports, O->ExportSize);
/* Imports */
- Write16 (NewLib, O->ImportSize);
+ WriteVar (NewLib, O->ImportSize);
WriteData (NewLib, O->Imports, O->ImportSize);
}
Header.IndexOffs = ftell (NewLib);
/* Write the object file count */
- Write16 (NewLib, ObjCount);
+ WriteVar (NewLib, ObjCount);
/* Write the object files */
O = ObjRoot;
return;
case EXPR_SYMBOL:
- /* 16 bit symbol index */
- *Buf += 2;
+ /* Variable seized symbol index */
+ (void) GetVar (Buf);
return;
case EXPR_SECTION:
}
/* What's left are unary and binary nodes */
- SkipExpr (Buf); /* Skip left */
- SkipExpr (Buf); /* Skip right */
+ SkipExpr (Buf); /* Skip left */
+ SkipExpr (Buf); /* Skip right */
}
while (Count--) {
unsigned char Tag;
- unsigned Len;
- char* Name;
+ const 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;
+ /* Next thing is index of name of symbol */
+ Name = GetObjString (O, GetVar (&Exports));
/* Skip value of symbol */
if (Tag & EXP_EXPR) {
/* Insert the name into the hash table */
Print (stdout, 1, " %s\n", Name);
ExpInsert (Name, O->Index);
-
- /* Free the name */
- xfree (Name);
}
}
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
ObjData* O = xmalloc (sizeof (ObjData));
/* Initialize the data */
- O->Next = 0;
- O->Name = 0;
- O->Index = ~0;
- O->Flags = 0;
- O->MTime = 0;
- O->Start = 0;
- O->Size = 0;
- O->ImportSize = 0;
- O->Imports = 0;
- O->ExportSize = 0;
- O->Exports = 0;
+ O->Next = 0;
+ O->Name = 0;
+ O->Index = ~0;
+ O->Flags = 0;
+ O->MTime = 0;
+ O->Start = 0;
+ O->Size = 0;
+ O->StringCount = 0;
+ O->Strings = 0;
+ O->ImportSize = 0;
+ O->Imports = 0;
+ O->ExportSize = 0;
+ O->Exports = 0;
/* Link it into the list */
if (ObjLast) {
void FreeObjData (ObjData* O)
/* Free a complete struct */
{
+ unsigned I;
+
xfree (O->Name);
xfree (O->Imports);
xfree (O->Exports);
+ for (I = 0; I < O->StringCount; ++I) {
+ xfree (O->Strings[I]);
+ }
+ xfree (O->Strings);
xfree (O);
}
/* Set the pool pointer */
ObjPool [Index] = O;
-
+
/* Next object */
++Index;
O = O->Next;
+const char* GetObjString (const ObjData* O, unsigned Index)
+/* Get a string from the string pool of an object file */
+{
+ if (Index >= O->StringCount) {
+ Error ("Invalid string index (%u) in module `%s'",
+ Index, GetObjName (O->Index));
+ }
+ return O->Strings[Index];
+}
+
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* Internal structure holding object file data */
-typedef struct ObjData_ ObjData;
-struct ObjData_ {
- ObjData* Next; /* Linked list of all objects */
- char* Name; /* Module name */
- unsigned Index; /* Module index */
- unsigned Flags;
+typedef struct ObjData ObjData;
+struct ObjData {
+ ObjData* Next; /* Linked list of all objects */
+ char* Name; /* Module name */
+ unsigned Index; /* Module index */
+ unsigned Flags;
unsigned long MTime; /* Modifiation time of object file */
unsigned long Start; /* Start offset of data in library */
unsigned long Size; /* Size of data in library */
+ unsigned StringCount; /* Number of strings */
+ char** Strings; /* Strings from the object file */
unsigned long ImportSize; /* Size of imports */
- void* Imports; /* Imports as raw data */
+ void* Imports; /* Imports as raw data */
unsigned long ExportSize; /* Size of exports */
- void* Exports; /* Exports as raw data */
+ void* Exports; /* Exports as raw data */
};
const char* GetObjName (unsigned Index);
/* Get the name of a module by index */
+const char* GetObjString (const ObjData* O, unsigned Index);
+/* Get a string from the string pool of an object file */
+
/* End of objdata.h */
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "xmalloc.h"
-
+
/* ar65 */
#include "error.h"
#include "objdata.h"
H->DbgSymSize = Read32 (Obj);
H->LineInfoOffs = Read32 (Obj);
H->LineInfoSize = Read32 (Obj);
+ H->StrPoolOffs = Read32 (Obj);
+ H->StrPoolSize = Read32 (Obj);
}
Write32 (Obj, H->DbgSymSize);
Write32 (Obj, H->LineInfoOffs);
Write32 (Obj, H->LineInfoSize);
+ Write32 (Obj, H->StrPoolOffs);
+ Write32 (Obj, H->StrPoolSize);
}
const char* Module;
ObjHeader H;
ObjData* O;
+ unsigned I;
/* Open the object file */
FILE* Obj = fopen (Name, "rb");
fseek (Obj, H.ExportOffs, SEEK_SET);
ReadData (Obj, O->Exports, O->ExportSize);
+ /* Read the string pool */
+ fseek (Obj, H.StrPoolOffs, SEEK_SET);
+ O->StringCount = ReadVar (Obj);
+ O->Strings = xmalloc (O->StringCount * sizeof (char*));
+ for (I = 0; I < O->StringCount; ++I) {
+ O->Strings[I] = ReadStr (Obj);
+ }
+
/* Skip the object file header */
O->Start = ftell (NewLib);
fseek (NewLib, OBJ_HDR_SIZE, SEEK_CUR);
O->Size = ftell (NewLib) - O->Start;
/* Clear the remaining header fields */
- H.ImportOffs = H.ImportSize = 0;
- H.ExportOffs = H.ExportSize = 0;
+ H.ImportOffs = H.ImportSize = 0;
+ H.ExportOffs = H.ExportSize = 0;
+ H.StrPoolOffs = H.StrPoolSize = 0;
/* Seek back and write the updated header */
fseek (NewLib, O->Start, SEEK_SET);
{
unsigned long ImportStart;
unsigned long ExportStart;
+ unsigned long StrPoolStart;
+ unsigned long StrPoolSize;
struct utimbuf U;
ObjHeader H;
FILE* Obj;
-
+ unsigned I;
/* Make a module name from the file name */
const char* Module = GetModule (Name);
ExportStart = ftell (Obj);
WriteData (Obj, O->Exports, O->ExportSize);
+ /* Write the string pool */
+ StrPoolStart = ftell (Obj);
+ WriteVar (Obj, O->StringCount);
+ for (I = 0; I < O->StringCount; ++I) {
+ WriteStr (Obj, O->Strings[I]);
+ }
+ StrPoolSize = ftell (Obj) - StrPoolStart;
+
/* Seek back and read the header */
fseek (Obj, 0, SEEK_SET);
ObjReadHeader (Obj, &H, Name);
/* Update the header fields */
- H.ImportOffs = ImportStart;
- H.ImportSize = O->ImportSize;
- H.ExportOffs = ExportStart;
- H.ExportSize = O->ExportSize;
+ H.ImportOffs = ImportStart;
+ H.ImportSize = O->ImportSize;
+ H.ExportOffs = ExportStart;
+ H.ExportSize = O->ExportSize;
+ H.StrPoolOffs = StrPoolStart;
+ H.StrPoolSize = StrPoolSize;
/* Write the changed header */
fseek (Obj, 0, SEEK_SET);
case EXPR_SYMBOL:
/* Maybe we should use a code here? */
CHECK (SymIsImport (Expr->V.Sym)); /* Safety */
- ObjWrite16 (GetSymIndex (Expr->V.Sym));
+ ObjWriteVar (GetSymIndex (Expr->V.Sym));
break;
case EXPR_SECTION:
/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
unsigned char LeadingDotInIdents = 0; /* Allow '.' to start an identifier */
unsigned char PCAssignment = 0; /* Allow "* = $XXX" or "$ = $XXX" */
+/* Misc stuff */
+const char Copyright[] = "(C) Copyright 1998-2003 Ullrich von Bassewitz";
+
/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
extern unsigned char LeadingDotInIdents; /* Allow '.' to start an identifier */
extern unsigned char PCAssignment; /* Allow "* = $XXX" or "$ = $XXX" */
+/* Misc stuff */
+extern const char Copyright[]; /* Copyright string */
+
/* End of global.h */
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
{
/* Print the header on the new page */
fprintf (F,
- "ca65 V%u.%u.%u - (C) Copyright 1998-2000 Ullrich von Bassewitz\n"
+ "ca65 V%u.%u.%u - %s\n"
"Main file : %s\n"
"Current file: %s\n"
"\n",
VER_MAJOR, VER_MINOR, VER_PATCH,
+ Copyright,
InFile,
GetFileName (L->File));
/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "options.h"
#include "pseudo.h"
#include "scanner.h"
+#include "spool.h"
#include "symtab.h"
#include "ulabel.h"
/* Print the assembler version */
{
fprintf (stderr,
- "ca65 V%u.%u.%u - (C) Copyright 1998-2000 Ullrich von Bassewitz\n",
- VER_MAJOR, VER_MINOR, VER_PATCH);
+ "ca65 V%u.%u.%u - %s\n",
+ VER_MAJOR, VER_MINOR, VER_PATCH, Copyright);
}
/* Write line infos if requested */
WriteLineInfo ();
+ /* Write the string pool */
+ WriteStrPool ();
+
/* Write an updated header and close the file */
ObjClose ();
}
}
/* If no CPU given, use the default CPU for the target */
- if (GetCPU () == CPU_UNKNOWN) {
+ if (GetCPU () == CPU_UNKNOWN) {
if (Target != TGT_UNKNOWN) {
SetCPU (DefaultCPU[Target]);
} else {
pseudo.o \
repeat.o \
scanner.o \
+ spool.o \
symtab.o \
toklist.o \
ulabel.o
pseudo.obj \
repeat.obj \
scanner.obj \
+ spool.obj \
symtab.obj \
toklist.obj \
ulabel.obj
void Emit0 (unsigned char OPC)
/* Emit an instruction with a zero sized operand */
{
- /* First fragment, wrong type or out of space, create new one */
Fragment* F = NewFragment (FRAG_LITERAL, 1);
F->V.Data [0] = OPC;
}
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* Header structure */
static ObjHeader Header = {
- OBJ_MAGIC,
- OBJ_VERSION,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ OBJ_MAGIC, /* 32: Magic number */
+ OBJ_VERSION, /* 16: Version number */
+ 0, /* 16: flags */
+ 0, /* 32: Offset to option table */
+ 0, /* 32: Size of options */
+ 0, /* 32: Offset to file table */
+ 0, /* 32: Size of files */
+ 0, /* 32: Offset to segment table */
+ 0, /* 32: Size of segment table */
+ 0, /* 32: Offset to import list */
+ 0, /* 32: Size of import list */
+ 0, /* 32: Offset to export list */
+ 0, /* 32: Size of export list */
+ 0, /* 32: Offset to list of debug symbols */
+ 0, /* 32: Size of debug symbols */
+ 0, /* 32: Offset to list of line infos */
+ 0, /* 32: Size of line infos */
+ 0, /* 32: Offset to string pool */
+ 0 /* 32: Size of string pool */
};
ObjWrite32 (Header.DbgSymSize);
ObjWrite32 (Header.LineInfoOffs);
ObjWrite32 (Header.LineInfoSize);
+ ObjWrite32 (Header.StrPoolOffs);
+ ObjWrite32 (Header.StrPoolSize);
}
+void ObjStartStrPool (void)
+/* Mark the start of the string pool section */
+{
+ Header.StrPoolOffs = ftell (F);
+}
+
+
+
+void ObjEndStrPool (void)
+/* Mark the end of the string pool section */
+{
+ Header.StrPoolSize = ftell (F) - Header.StrPoolOffs;
+}
+
+
+
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
void ObjEndLineInfos (void);
/* Mark the end of the line info section */
+void ObjStartStrPool (void);
+/* Mark the start of the string pool section */
+
+void ObjEndStrPool (void);
+/* Mark the end of the string pool section */
-/* End of objfile.h */
+/* End of objfile.h */
+
#endif
--- /dev/null
+/*****************************************************************************/
+/* */
+/* spool.c */
+/* */
+/* Id and message pool for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+/* ca65 */
+#include "objfile.h"
+#include "spool.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+StringPool StrPool = STATIC_STRINGPOOL_INITIALIZER;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void WriteStrPool (void)
+/* Write the string pool to the object file */
+{
+ unsigned I;
+
+ /* Get the number of strings in the string pool */
+ unsigned Count = SP_GetCount (&StrPool);
+
+ /* Tell the object file module that we're about to start the string pool */
+ ObjStartStrPool ();
+
+ /* Write the string count to the list */
+ ObjWriteVar (Count);
+
+ /* Write the strings in id order */
+ for (I = 0; I < Count; ++I) {
+ ObjWriteStr (SP_Get (&StrPool, I));
+ }
+
+ /* Done writing the string pool */
+ ObjEndStrPool ();
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* spool.h */
+/* */
+/* Id and message pool for the ca65 macroassembler */
+/* */
+/* */
+/* */
+/* (C) 2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef SPOOL_H
+#define SPOOL_H
+
+
+
+/* common */
+#include "strpool.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+extern StringPool StrPool;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+#if defined(HAVE_INLINE)
+INLINE unsigned GetStringId (const char* S)
+/* Return the id of the given string */
+{
+ return SP_Add (&StrPool, S);
+}
+#else
+# define GetStringId(S) SP_Add (&StrPool, (S))
+#endif
+
+void WriteStrPool (void);
+/* Write the string pool to the object file */
+
+
+
+/* End of spool.h */
+
+#endif
+
+
+
+
#include "expr.h"
#include "objfile.h"
#include "scanner.h"
+#include "spool.h"
#include "symtab.h"
} else {
ObjWrite8 (IMP_ABS);
}
- ObjWriteStr (S->Name);
+ ObjWriteVar (GetStringId (S->Name));
ObjWritePos (&S->Pos);
}
S = S->List;
}
/* Write the name */
- ObjWriteStr (S->Name);
+ ObjWriteVar (GetStringId (S->Name));
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
ObjWrite8 (ExprMask);
/* Write the name */
- ObjWriteStr (S->Name);
+ ObjWriteVar (GetStringId (S->Name));
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
#define STATIC_COLLECTION_INITIALIZER { 0, 0, 0 }
/* Initializer for auto collections */
-#define AUTO_COLLECTION_INITIALIZER EmptyCollection;
+#define AUTO_COLLECTION_INITIALIZER EmptyCollection
-
+
/*****************************************************************************/
/* */
-/* libdefs.h */
+/* libdefs.h */
/* */
/* Library file definitions */
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* Defines for magic and version */
#define LIB_MAGIC 0x7A55616E
-#define LIB_VERSION 0x0009
+#define LIB_VERSION 0x000A
/* Size of an library file header */
#define LIB_HDR_SIZE 12
/* Header structure for the library */
-typedef struct LibHeader_ LibHeader;
-struct LibHeader_ {
+typedef struct LibHeader LibHeader;
+struct LibHeader {
unsigned long Magic; /* 32: Magic number */
unsigned Version; /* 16: Version number */
unsigned Flags; /* 16: flags */
segdefs.o \
segnames.o \
strbuf.o \
+ strpool.o \
strutil.o \
target.o \
tgttrans.o \
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* Defines for magic and version */
#define OBJ_MAGIC 0x616E7A55
-#define OBJ_VERSION 0x0009
+#define OBJ_VERSION 0x000A
/* Size of an object file header */
-#define OBJ_HDR_SIZE 64
+#define OBJ_HDR_SIZE 72
/* Flag bits */
#define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */
/* Header structure */
-typedef struct ObjHeader_ ObjHeader;
-struct ObjHeader_ {
+typedef struct ObjHeader ObjHeader;
+struct ObjHeader {
unsigned long Magic; /* 32: Magic number */
unsigned Version; /* 16: Version number */
unsigned Flags; /* 16: flags */
unsigned long DbgSymSize; /* 32: Size of debug symbols */
unsigned long LineInfoOffs; /* 32: Offset to list of line infos */
unsigned long LineInfoSize; /* 32: Size of line infos */
+ unsigned long StrPoolOffs; /* 32: Offset to string pool */
+ unsigned long StrPoolSize; /* 32: Size of string pool */
};
/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
+/* (C) 1998-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* Available segment types */
-#define SEGTYPE_DEFAULT 0
-#define SEGTYPE_ABS 1
-#define SEGTYPE_ZP 2
-#define SEGTYPE_FAR 3
+#define SEGTYPE_DEFAULT 0
+#define SEGTYPE_ABS 1
+#define SEGTYPE_ZP 2
+#define SEGTYPE_FAR 3
/* Fragment types in the object file */
-#define FRAG_TYPEMASK 0x38 /* Mask the type of the fragment */
-#define FRAG_BYTEMASK 0x07 /* Mask for byte count */
-
-#define FRAG_LITERAL 0x00 /* Literal data */
-
-#define FRAG_EXPR 0x08 /* Expression */
-#define FRAG_EXPR8 0x09 /* 8 bit expression */
-#define FRAG_EXPR16 0x0A /* 16 bit expression */
-#define FRAG_EXPR24 0x0B /* 24 bit expression */
-#define FRAG_EXPR32 0x0C /* 32 bit expression */
-
-#define FRAG_SEXPR 0x10 /* Signed expression */
-#define FRAG_SEXPR8 0x11 /* 8 bit signed expression */
-#define FRAG_SEXPR16 0x12 /* 16 bit signed expression */
-#define FRAG_SEXPR24 0x13 /* 24 bit signed expression */
-#define FRAG_SEXPR32 0x14 /* 32 bit signed expression */
-
-#define FRAG_FILL 0x20 /* Fill bytes */
+#define FRAG_TYPEMASK 0x38 /* Mask the type of the fragment */
+#define FRAG_BYTEMASK 0x07 /* Mask for byte count */
+#define FRAG_CHECKMASK 0xC0 /* Mask for check type */
+
+/* Fragment types */
+#define FRAG_LITERAL 0x00 /* Literal data */
+
+#define FRAG_EXPR 0x08 /* Expression */
+#define FRAG_EXPR8 0x09 /* 8 bit expression */
+#define FRAG_EXPR16 0x0A /* 16 bit expression */
+#define FRAG_EXPR24 0x0B /* 24 bit expression */
+#define FRAG_EXPR32 0x0C /* 32 bit expression */
+
+#define FRAG_SEXPR 0x10 /* Signed expression */
+#define FRAG_SEXPR8 0x11 /* 8 bit signed expression */
+#define FRAG_SEXPR16 0x12 /* 16 bit signed expression */
+#define FRAG_SEXPR24 0x13 /* 24 bit signed expression */
+#define FRAG_SEXPR32 0x14 /* 32 bit signed expression */
+
+#define FRAG_FILL 0x20 /* Fill bytes */
+
+/* Fragment checks */
+#define FRAG_CHECK_NONE 0x00 /* No checks applied */
+#define FRAG_CHECK_WARN 0x40 /* Check and warn */
+#define FRAG_CHECK_ERROR 0x80 /* Check and abort */
/* A string pool entry */
-struct StrPoolEntry {
- StrPoolEntry* Next; /* Pointer to next entry in hash chain */
+struct StringPoolEntry {
+ StringPoolEntry* Next; /* Pointer to next entry in hash chain */
unsigned Hash; /* Full hash value */
unsigned Id; /* The numeric string id */
unsigned Len; /* Length of the string (excluding terminator) */
/*****************************************************************************/
-/* struct StrPoolEntry */
+/* struct StringPoolEntry */
/*****************************************************************************/
-static StrPoolEntry* NewStrPoolEntry (const char* S, unsigned Hash, unsigned Id)
+static StringPoolEntry* NewStringPoolEntry (const char* S, unsigned Hash, unsigned Id)
/* Create a new string pool entry and return it. */
{
/* Get the length of the string */
unsigned Len = strlen (S);
/* Allocate memory */
- StrPoolEntry* E = xmalloc (sizeof (StrPoolEntry) + Len);
+ StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry) + Len);
/* Initialize the fields */
E->Next = 0;
-StrPool* InitStrPool (StrPool* P)
+StringPool* InitStringPool (StringPool* P)
/* Initialize a string pool */
{
unsigned I;
-void DoneStrPool (StrPool* P)
+void DoneStringPool (StringPool* P)
/* Free the data of a string pool (but not the data itself) */
{
unsigned I;
-StrPool* NewStrPool (void)
+StringPool* NewStringPool (void)
/* Allocate, initialize and return a new string pool */
{
/* Allocate memory, initialize and return it */
- return InitStrPool (xmalloc (sizeof (StrPool)));
+ return InitStringPool (xmalloc (sizeof (StringPool)));
}
-void FreeStrPool (StrPool* P)
+void FreeStringPool (StringPool* P)
/* Free a string pool */
{
/* Free all entries */
- DoneStrPool (P);
+ DoneStringPool (P);
/* Free the string pool itself */
xfree (P);
-const char* SP_Get (const StrPool* P, unsigned Index)
+const char* SP_Get (const StringPool* P, unsigned Index)
/* Return a string from the pool. Index must exist, otherwise FAIL is called. */
{
/* Get the collection entry */
- const StrPoolEntry* E = CollConstAt (&P->Entries, Index);
+ const StringPoolEntry* E = CollConstAt (&P->Entries, Index);
/* Return the string from the entry */
return E->S;
-unsigned SP_Add (StrPool* P, const char* S)
+unsigned SP_Add (StringPool* P, const char* S)
/* Add a string to the buffer and return the index. If the string does already
* exist in the pool, SP_Add will just return the index of the existing string.
*/
unsigned RHash = Hash % (sizeof (P->Tab)/sizeof (P->Tab[0]));
/* Search for an existing entry */
- StrPoolEntry* E = P->Tab[RHash];
+ StringPoolEntry* E = P->Tab[RHash];
while (E) {
if (E->Hash == Hash && strcmp (E->S, S) == 0) {
/* Found, return the id of the existing string */
}
/* We didn't find the entry, so create a new one */
- E = NewStrPoolEntry (S, Hash, CollCount (&P->Entries));
+ E = NewStringPoolEntry (S, Hash, CollCount (&P->Entries));
/* Insert the new entry into the entry collection */
CollAppend (&P->Entries, E);
-unsigned SP_AddBuf (StrPool* P, const void* Buffer, unsigned Size)
-/* Add strings from a string buffer. Buffer must contain a list of zero
- * terminated strings. These strings are added to the pool, starting with
- * the current index. The number of strings added is returned.
- * Beware: The function will do only loose range checking for the buffer
- * limits, so a SEGV may occur if the last string in the buffer is not
- * correctly terminated.
- */
-{
- /* Cast the buffer pointer to something useful */
- const char* Buf = Buffer;
-
- /* Remember the current number of strings in the buffer. */
- unsigned OldCount = SB_GetCount (P);
-
- /* Add all strings from the buffer */
- while (Size) {
-
- /* Add the next entry */
- unsigned Id = SP_Add (P, Buf);
-
- /* Get the entry from the id */
- const StrPoolEntry* E = CollConstAt (&P->Entries, Id);
-
- /* Skip this string */
- Buf += E->Len + 1;
- Size -= E->Len + 1;
- }
-
- /* Return the number of strings added */
- return SB_GetCount (P) - OldCount;
-}
-
-
-
-void SP_Build (StrPool* P, const void* Buffer, unsigned Size)
-/* Delete existing data and use the data from Buffer instead. */
-{
- /* Delete old data */
- DoneStrPool (P);
-
- /* Add the buffer data */
- SP_AddBuf (P, Buffer, Size);
-}
-
-
-
-/* Opaque entry */
-typedef struct StrPoolEntry StrPoolEntry;
-
-typedef struct StrPool StrPool;
-struct StrPool {
- StrPoolEntry* Tab[211]; /* Entry hash table */
- Collection Entries; /* Entries sorted by number */
- unsigned TotalSize; /* Total size of all string data */
+/* Opaque string pool entry */
+typedef struct StringPoolEntry StringPoolEntry;
+
+/* A string pool */
+typedef struct StringPool StringPool;
+struct StringPool {
+ Collection Entries; /* Entries sorted by number */
+ unsigned TotalSize; /* Total size of all string data */
+ StringPoolEntry* Tab[211]; /* Entry hash table */
};
+/* A string pool initializer. We do only initialize the first field, all
+ * others will get zeroed out by the compiler.
+ */
+#define STATIC_STRINGPOOL_INITIALIZER { \
+ STATIC_COLLECTION_INITIALIZER, \
+ 0, \
+ { 0 } \
+}
+
/*****************************************************************************/
-StrPool* InitStrPool (StrPool* P);
+StringPool* InitStringPool (StringPool* P);
/* Initialize a string pool */
-void DoneStrPool (StrPool* P);
+void DoneStringPool (StringPool* P);
/* Free the data of a string pool (but not the data itself) */
-StrPool* NewStrPool (void);
+StringPool* NewStringPool (void);
/* Allocate, initialize and return a new string pool */
-void FreeStrPool (StrPool* P);
+void FreeStringPool (StringPool* P);
/* Free a string pool */
-void SP_Use (char* Buffer, unsigned Size);
-/* Delete existing data and use the data from Buffer instead. Buffer must be
- * allocated on the heap and will be freed using xfree() if necessary.
- */
-
-const char* SP_Get (const StrPool* P, unsigned Index);
+const char* SP_Get (const StringPool* P, unsigned Index);
/* Return a string from the pool. Index must exist, otherwise FAIL is called. */
-unsigned SP_Add (StrPool* P, const char* S);
+unsigned SP_Add (StringPool* P, const char* S);
/* Add a string to the buffer and return the index. If the string does already
* exist in the pool, SP_Add will just return the index of the existing string.
*/
#if defined(HAVE_INLINE)
-INLINE unsigned SB_GetCount (const StrPool* P)
+INLINE unsigned SP_GetCount (const StringPool* P)
/* Return the number of strings in the pool */
{
return CollCount (&P->Entries);
}
#else
-# define SB_GetCount(P) CollCount (&(P)->Entries)
+# define SP_GetCount(P) CollCount (&(P)->Entries)
#endif
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
D->Flags = 0;
D->Obj = O;
D->Expr = 0;
- D->Type = Type;
D->Name = 0;
+ D->Type = Type;
/* Return the new entry */
return D;
D = NewDbgSym (Type, O);
/* Read and assign the name */
- D->Name = ReadStr (F);
+ D->Name = GetObjString (O, ReadVar (F));
/* Read the value */
if (IS_EXP_EXPR (Type)) {
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
ObjData* Obj; /* Object file that exports the name */
FilePos Pos; /* File position of definition */
ExprNode* Expr; /* Expression (0 if not def'd) */
+ const char* Name; /* Name */
unsigned char Type; /* Type of symbol */
- char* Name; /* Name - dynamically allocated */
};
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
unsigned HashVal;
/* As long as the import is not inserted, V.Name is valid */
- char* Name = I->V.Name;
+ const char* Name = I->V.Name;
/* Create a hash value for the given name */
HashVal = HashStr (Name) % HASHTAB_SIZE;
if (E->Next == 0) {
/* End of list an entry not found, insert a dummy */
E->Next = NewExport (0, Name, 0);
- E = E->Next; /* Point to dummy */
- ++ExpCount; /* One export more */
+ E = E->Next; /* Point to dummy */
+ ++ExpCount; /* One export more */
break;
} else {
E = E->Next;
I->Next = E->ImpList;
E->ImpList = I;
E->ImpCount++;
- ++ImpCount; /* Total import count */
+ ++ImpCount; /* Total import count */
if (E->Expr == 0) {
/* This is a dummy export */
++ImpOpen;
}
-
- /* Now free the name since it's no longer needed */
- xfree (Name);
}
I = NewImport (Type, Obj);
/* Read the name */
- I->V.Name = ReadStr (F);
+ I->V.Name = GetObjString (Obj, ReadVar (F));
/* Read the file position */
ReadFilePos (F, &I->Pos);
}
/* Read the name */
- E->Name = ReadStr (F);
+ E->Name = GetObjString (O, ReadVar (F));
/* Read the value */
if (IS_EXP_EXPR (Type)) {
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
FilePos Pos; /* File position of reference */
union {
struct Export* Exp; /* Matching export for this import */
- char* Name; /* Name if not in table */
+ const char* Name; /* Name if not in table */
} V;
unsigned char Type; /* Type of import */
};
ExprNode* Expr; /* Expression (0 if not def'd) */
unsigned char Type; /* Type of export */
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
- char* Name; /* Name - dynamically allocated */
+ const char* Name; /* Name */
};
case EXPR_SYMBOL:
/* Read the import number */
- Expr->V.ImpNum = Read16 (F);
+ Expr->V.ImpNum = ReadVar (F);
break;
case EXPR_SECTION:
/* Not a leaf node */
Expr->Left = ReadExpr (F, O);
- Expr->Right = ReadExpr (F, O);
+ Expr->Right = ReadExpr (F, O);
}
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* Create a new fragment and insert it into the section S */
{
/* Allocate memory */
- Fragment* F = xmalloc (sizeof (Fragment) - 1 + Size); /* Portable? */
+ Fragment* F = xmalloc (sizeof (Fragment) - 1 + Size);
/* Initialize the data */
- F->Next = 0;
- F->Obj = 0;
- F->Size = Size;
- F->Expr = 0;
+ F->Next = 0;
+ F->Obj = 0;
+ F->Size = Size;
+ F->Expr = 0;
InitFilePos (&F->Pos);
- F->LI = 0;
- F->Type = Type;
+ F->LI = 0;
+ F->WarnExpr = 0;
+ F->ErrorExpr = 0;
+ F->Type = Type;
/* Insert the code fragment into the section */
if (S->FragRoot == 0) {
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
struct ExprNode* Expr; /* Expression if FRAG_EXPR */
FilePos Pos; /* File position in source */
struct LineInfo* LI; /* Additional line info */
+ struct ExprNode* WarnExpr; /* Print warning if expr true */
+ struct ExprNode* ErrorExpr; /* Print error if expr true */
unsigned char Type; /* Type of fragment */
unsigned char LitBuf [1]; /* Dynamically alloc'ed literal buffer */
};
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
O->Header.DbgSymSize = Read32 (Lib);
O->Header.LineInfoOffs = Read32 (Lib);
O->Header.LineInfoSize = Read32 (Lib);
+ O->Header.StrPoolOffs = Read32 (Lib);
+ O->Header.StrPoolSize = Read32 (Lib);
}
O->Start = Read32 (Lib);
Read32 (Lib); /* Skip Size */
+ /* Read the string pool */
+ ObjReadStrPool (Lib, O);
+
/* Skip the export size, then read the exports */
- Read16 (Lib);
+ (void) ReadVar (Lib);
O->ExportCount = ReadVar (Lib);
O->Exports = xmalloc (O->ExportCount * sizeof (Export*));
for (I = 0; I < O->ExportCount; ++I) {
- O->Exports [I] = ReadExport (Lib, O);
+ O->Exports[I] = ReadExport (Lib, O);
}
/* Skip the import size, then read the imports */
- Read16 (Lib);
+ (void) ReadVar (Lib);
O->ImportCount = ReadVar (Lib);
O->Imports = xmalloc (O->ImportCount * sizeof (Import*));
for (I = 0; I < O->ImportCount; ++I) {
- O->Imports [I] = ReadImport (Lib, O);
+ O->Imports[I] = ReadImport (Lib, O);
}
/* Done */
unsigned I;
/* Read the object file count and allocate memory */
- ModuleCount = Read16 (Lib);
+ ModuleCount = ReadVar (Lib);
Index = xmalloc (ModuleCount * sizeof (ObjData*));
/* Read all entries in the index */
for (I = 0; I < ModuleCount; ++I) {
- Index [I] = ReadIndexEntry ();
+ Index[I] = ReadIndexEntry ();
}
}
/*****************************************************************************/
-/* High level stuff */
+/* High level stuff */
/*****************************************************************************/
/* Check all exports */
for (I = 0; I < O->ExportCount; ++I) {
- if (IsUnresolved (O->Exports [I]->Name)) {
+ if (IsUnresolved (O->Exports[I]->Name)) {
/* We need this module */
O->Flags |= OBJ_REF;
break;
if (O->Flags & OBJ_REF) {
/* Insert the exports */
for (I = 0; I < O->ExportCount; ++I) {
- InsertExport (O->Exports [I]);
+ InsertExport (O->Exports[I]);
}
/* Insert the imports */
- for (I = 0; I < O->ImportCount; ++I) {
- InsertImport (O->Imports [I]);
+ for (I = 0; I < O->ImportCount; ++I) {
+ InsertImport (O->Imports[I]);
}
}
}
Header.Magic = LIB_MAGIC;
Header.Version = Read16 (Lib);
if (Header.Version != LIB_VERSION) {
- Error ("Wrong data version in `%s'", Name);
+ Error ("Wrong data version in `%s'", Name);
}
Header.Flags = Read16 (Lib);
Header.IndexOffs = Read32 (Lib);
/* Seek to the start of the debug info and read the debug info */
fseek (Lib, O->Start + O->Header.DbgSymOffs, SEEK_SET);
- ObjReadDbgSyms (Lib, O);
+ ObjReadDbgSyms (Lib, O);
/* Seek to the start of the line infos and read them */
fseek (Lib, O->Start + O->Header.LineInfoOffs, SEEK_SET);
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
O->DbgSyms = 0;
O->LineInfoCount = 0;
O->LineInfos = 0;
+ O->StringCount = 0;
+ O->Strings = 0;
/* Link it into the list */
if (ObjLast) {
-void FreeObjData (ObjData* O)
-/* Free a complete struct */
+const char* GetObjString (const ObjData* O, unsigned long Index)
+/* Get a string from the object file string table. Abort if the string index
+ * is invalid.
+ */
{
- xfree (O->Name);
- xfree (O->Imports);
- xfree (O->Exports);
- xfree (O->DbgSyms);
- xfree (O->LineInfos);
- xfree (O);
+ if (Index >= O->StringCount) {
+ Error ("Invalid string index (%lu) in module `%s'",
+ Index, GetObjFileName (O));
+ }
+ return O->Strings[Index];
}
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
struct DbgSym** DbgSyms; /* List of debug symbols */
unsigned LineInfoCount; /* Count of additional line infos */
struct LineInfo** LineInfos; /* List of additional line infos */
+ unsigned StringCount; /* Count of strings */
+ char** Strings; /* List of strings used */
};
ObjData* NewObjData (void);
/* Allocate a new structure on the heap, insert it into the list, return it */
-void FreeObjData (ObjData* O);
-/* Free a complete struct */
+const char* GetObjString (const ObjData* O, unsigned long Index);
+/* Get a string from the object file string table. Abort if the string index
+ * is invalid.
+ */
const char* GetObjFileName (const ObjData* O);
/* Get the name of the object file. Return "[linker generated]" if the object
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
{
H->Version = Read16 (Obj);
if (H->Version != OBJ_VERSION) {
- Error ("Object file `%s' has wrong version", Name);
+ Error ("Object file `%s' has wrong version, expected %08X, got %08X",
+ Name, OBJ_VERSION, H->Version);
}
H->Flags = Read16 (Obj);
H->OptionOffs = Read32 (Obj);
H->DbgSymSize = Read32 (Obj);
H->LineInfoOffs = Read32 (Obj);
H->LineInfoSize = Read32 (Obj);
+ H->StrPoolOffs = Read32 (Obj);
+ H->StrPoolSize = Read32 (Obj);
}
+void ObjReadStrPool (FILE* F, ObjData* O)
+/* Read the string pool from a file at the current position */
+{
+ unsigned I;
+ O->StringCount = ReadVar (F);
+ O->Strings = xmalloc (O->StringCount * sizeof (char*));
+ for (I = 0; I < O->StringCount; ++I) {
+ O->Strings[I] = ReadStr (F);
+ }
+}
+
+
+
void ObjReadSections (FILE* F, ObjData* O)
/* Read the section data from a file at the current position */
{
O->Name = xstrdup (GetModule (Name));
O->Flags = OBJ_HAVEDATA;
+ /* Read the string pool from the object file */
+ fseek (Obj, O->Header.StrPoolOffs, SEEK_SET);
+ ObjReadStrPool (Obj, O);
+
/* Read the files list from the object file */
fseek (Obj, O->Header.FileOffs, SEEK_SET);
ObjReadFiles (Obj, O);
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* common */
#include "objdefs.h"
-
+
/* ld65 */
#include "objdata.h"
void ObjReadLineInfos (FILE* F, ObjData* O);
/* Read the line infos from a file at the current position */
+void ObjReadStrPool (FILE* F, ObjData* O);
+/* Read the string pool from a file at the current position */
+
void ObjReadSections (FILE* F, ObjData* O);
/* Read the section data from a file at the current position */
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* Read the fragment type */
unsigned char Type = Read8 (F);
+ /* Extract the check mask from the type */
+ unsigned char Check = Type & FRAG_CHECKMASK;
+ Type &= ~FRAG_CHECKMASK;
+
/* Handle the different fragment types */
switch (Type) {
}
+ /* A check expression may follow */
+ if (Check & FRAG_CHECK_WARN) {
+ Frag->WarnExpr = ReadExpr (F, O);
+ }
+ if (Check & FRAG_CHECK_ERROR) {
+ Frag->ErrorExpr = ReadExpr (F, O);
+ }
+
/* Read the file position of the fragment */
ReadFilePos (F, &Frag->Pos);
/* Loop over all fragments in this section */
Frag = Sec->FragRoot;
while (Frag) {
+
+ /* Do fragment alignment checks */
+
+
+ /* Output fragment data */
switch (Frag->Type) {
case FRAG_LITERAL:
case SEG_EXPR_RANGE_ERROR:
Error ("Range error in module `%s', line %lu",
GetSourceFileName (Frag->Obj, Frag->Pos.Name),
- Frag->Pos.Line);
+ Frag->Pos.Line);
break;
case SEG_EXPR_TOO_COMPLEX:
/* */
/* */
/* */
-/* (C) 2000-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
+/* (C) 2002-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* common */
#include "cddefs.h"
+#include "coll.h"
#include "exprdefs.h"
#include "filepos.h"
#include "objdefs.h"
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
+static void DestroyStrPool (Collection* C)
+/* Free all strings in the given pool plus the item pointers. Note: The
+ * collection may not be reused later.
+ */
+{
+ unsigned I;
+ for (I = 0; I < CollCount (C); ++I) {
+ xfree (CollAtUnchecked (C, I));
+ }
+ DoneCollection (C);
+}
+
+
+
+static const char* GetString (const Collection* C, unsigned Index)
+/* Get a string from a collection. In fact, this function calls CollConstAt,
+ * but will print a somewhat more readable error message if the index is out
+ * of bounds.
+ */
+{
+ if (Index >= CollCount (C)) {
+ Error ("Invalid string index (%u) - file corrupt!", Index);
+ }
+ return CollConstAt (C, Index);
+}
+
+
+
static void DumpObjHeaderSection (const char* Name,
unsigned long Offset,
unsigned long Size)
case EXPR_SYMBOL:
/* Read the import number */
- (void) Read16 (F);
+ (void) ReadVar (F);
break;
case EXPR_SECTION:
/* Read the fragment type */
unsigned char Type = Read8 (F);
+ /* Extract the check mask */
+ unsigned char Check = Type & FRAG_CHECKMASK;
+ Type &= ~FRAG_CHECKMASK;
+
/* Handle the different fragment types */
switch (Type) {
}
+ /* Skip the check expression if we have one */
+ if (Check & FRAG_CHECK_WARN) {
+ SkipExpr (F);
+ }
+ if (Check & FRAG_CHECK_ERROR) {
+ SkipExpr (F);
+ }
+
/* Skip the file position of the fragment */
ReadFilePos (F, &Pos);
/* Debug symbols */
DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
+
+ /* Line infos */
+ DumpObjHeaderSection ("Line infos", H.LineInfoOffs, H.LineInfoSize);
+
+ /* String pool */
+ DumpObjHeaderSection ("String pool", H.StrPoolOffs, H.StrPoolSize);
}
void DumpObjOptions (FILE* F, unsigned long Offset)
/* Dump the file options */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the options */
FileSeek (F, Offset + H.OptionOffs);
break;
}
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjFiles (FILE* F, unsigned long Offset)
/* Dump the source files */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the source files */
FileSeek (F, Offset + H.FileOffs);
/* Free the Name */
xfree (Name);
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjSegments (FILE* F, unsigned long Offset)
/* Dump the segments in the object file */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
- unsigned FragCount;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
+ unsigned FragCount;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the segments */
FileSeek (F, Offset + H.SegOffs);
/* Read and print all segments */
for (I = 0; I < Count; ++I) {
-
+
/* Read the data for one segments */
char* Name = ReadStr (F);
unsigned Len = strlen (Name);
while (Size > 0) {
unsigned FragSize = SkipFragment (F);
if (FragSize > Size) {
- /* OOPS - file data invalid */
- Error ("Invalid fragment data - file corrupt!");
+ /* OOPS - file data invalid */
+ Error ("Invalid fragment data - file corrupt!");
}
Size -= FragSize;
++FragCount;
/* Print the fragment count */
printf (" Fragment count:%16u\n", FragCount);
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjImports (FILE* F, unsigned long Offset)
/* Dump the imports in the object file */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
- FilePos Pos;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
+ FilePos Pos;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the imports */
FileSeek (F, Offset + H.ImportOffs);
/* Read the data for one import */
unsigned char Type = Read8 (F);
- char* Name = ReadStr (F);
+ const char* Name = GetString (&StrPool, ReadVar (F));
unsigned Len = strlen (Name);
ReadFilePos (F, &Pos);
/* Print the data */
printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
-
- /* Free the Name */
- xfree (Name);
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjExports (FILE* F, unsigned long Offset)
/* Dump the exports in the object file */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
- FilePos Pos;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
+ FilePos Pos;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the exports */
FileSeek (F, Offset + H.ExportOffs);
for (I = 0; I < Count; ++I) {
unsigned long Value = 0;
- int HaveValue;
+ int HaveValue;
unsigned char Type;
unsigned char ConDes [CD_TYPE_COUNT];
- char* Name;
+ const char* Name;
unsigned Len;
/* Read the data for one export */
Type = Read8 (F);
ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type));
- Name = ReadStr (F);
+ Name = GetString (&StrPool, ReadVar (F));
Len = strlen (Name);
if (IS_EXP_EXPR (Type)) {
SkipExpr (F);
if (HaveValue) {
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
}
-
- /* Free the Name */
- xfree (Name);
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjDbgSyms (FILE* F, unsigned long Offset)
/* Dump the debug symbols from an object file */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
- FilePos Pos;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
+ FilePos Pos;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the debug syms */
FileSeek (F, Offset + H.DbgSymOffs);
int HaveValue;
unsigned char Type;
unsigned char ConDes [CD_TYPE_COUNT];
- char* Name;
+ const char* Name;
unsigned Len;
/* Read the data for one symbol */
Type = Read8 (F);
ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type));
- Name = ReadStr (F);
+ Name = GetString (&StrPool, ReadVar (F));
Len = strlen (Name);
if (IS_EXP_EXPR (Type)) {
SkipExpr (F);
if (HaveValue) {
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
}
-
- /* Free the Name */
- xfree (Name);
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjLineInfo (FILE* F, unsigned long Offset)
/* Dump the line info from an object file */
{
- ObjHeader H;
- unsigned Count;
- unsigned I;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
+ unsigned I;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of line infos */
FileSeek (F, Offset + H.LineInfoOffs);
printf (" Col:%27u\n", Pos.Col);
printf (" Name:%26u\n", Pos.Name);
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
void DumpObjSegSize (FILE* F, unsigned long Offset)
/* Dump the sizes of the segment in the object file */
{
- ObjHeader H;
- unsigned Count;
+ ObjHeader H;
+ Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+ unsigned Count;
- /* Seek to the header position */
+ /* Seek to the header position and read the header */
FileSeek (F, Offset);
-
- /* Read the header */
ReadObjHeader (F, &H);
+ /* Seek to the start of the string pool and read it */
+ FileSeek (F, Offset + H.StrPoolOffs);
+ ReadStrPool (F, &StrPool);
+
/* Seek to the start of the segments */
FileSeek (F, Offset + H.SegOffs);
Size -= FragSize;
}
}
+
+ /* Destroy the string pool */
+ DestroyStrPool (&StrPool);
}
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
H->DbgSymSize = Read32 (F);
H->LineInfoOffs = Read32 (F);
H->LineInfoSize = Read32 (F);
+ H->StrPoolOffs = Read32 (F);
+ H->StrPoolSize = Read32 (F);
+}
+
+
+
+void ReadStrPool (FILE* F, Collection* C)
+/* Read a string pool from the current position into C. */
+{
+ /* The number of strings is the first item */
+ unsigned long Count = ReadVar (F);
+
+ /* Read all the strings into C */
+ while (Count--) {
+ CollAppend (C, ReadStr (F));
+ }
}
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdio.h>
/* common */
+#include "coll.h"
#include "filepos.h"
#include "objdefs.h"
void ReadObjHeader (FILE* F, ObjHeader* Header);
/* Read an object file header from the file */
+void ReadStrPool (FILE* F, Collection* C);
+/* Read a string pool from the current position into C. */
+
/* End of fileio.h */