/* common */
#include "check.h"
#include "fname.h"
-#include "segdefs.h"
+#include "fragdefs.h"
#include "version.h"
#include "xmalloc.h"
/* common */
#include "chartype.h"
#include "check.h"
+#include "fragdefs.h"
#include "segdefs.h"
#include "segnames.h"
#include "xmalloc.h"
#include "global.h"
#include "lineinfo.h"
#include "listing.h"
+#include "objcode.h"
#include "objfile.h"
#include "scanner.h"
+#include "spool.h"
#include "symtab.h"
-#include "objcode.h"
ObjWrite32 (0);
/* Write the segment data */
- ObjWriteStr (Seg->Def->Name); /* Name of the segment */
- ObjWrite32 (Seg->PC); /* Size */
- ObjWrite8 (Seg->Align); /* Segment alignment */
- ObjWrite8 (Seg->Def->Type); /* Type of the segment */
- ObjWriteVar (Seg->FragCount); /* Number of fragments that follow */
+ ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */
+ ObjWrite32 (Seg->PC); /* Size */
+ ObjWrite8 (Seg->Align); /* Segment alignment */
+ ObjWrite8 (Seg->Def->Type); /* Type of the segment */
+ ObjWriteVar (Seg->FragCount); /* Number of fragments */
/* Now walk through the fragment list for this segment and write the
* fragments.
--- /dev/null
+/*****************************************************************************/
+/* */
+/* fragdefs.h */
+/* */
+/* Fragment definitions for the bin65 binary utils */
+/* */
+/* */
+/* */
+/* (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 */
+/* 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 FRAGDEFS_H
+#define FRAGDEFS_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Masks for the fragment type byte */
+#define FRAG_TYPEMASK 0x38 /* Mask the type of the fragment */
+#define FRAG_BYTEMASK 0x07 /* Mask for byte count */
+#define FRAG_CHECKMASK 0x40 /* Mask for check expressions */
+
+/* Fragment types */
+#define FRAG_LITERAL 0x00 /* Literal data */
+
+#define FRAG_EXPR 0x08 /* Expression */
+#define FRAG_EXPR8 (FRAG_EXPR | 1) /* 8 bit expression */
+#define FRAG_EXPR16 (FRAG_EXPR | 2) /* 16 bit expression */
+#define FRAG_EXPR24 (FRAG_EXPR | 3) /* 24 bit expression */
+#define FRAG_EXPR32 (FRAG_EXPR | 4) /* 32 bit expression */
+
+#define FRAG_SEXPR 0x10 /* Signed expression */
+#define FRAG_SEXPR8 (FRAG_SEXPR | 1)/* 8 bit signed expression */
+#define FRAG_SEXPR16 (FRAG_SEXPR | 2)/* 16 bit signed expression */
+#define FRAG_SEXPR24 (FRAG_SEXPR | 3)/* 24 bit signed expression */
+#define FRAG_SEXPR32 (FRAG_SEXPR | 4)/* 32 bit signed expression */
+
+#define FRAG_FILL 0x20 /* Fill bytes */
+
+/* Fragment checks */
+#define FRAG_CHECK 0x40 /* Check expressions exist */
+
+/* Fragment check actions */
+#define FRAG_ACT_WARN 0x00U /* Print a warning */
+#define FRAG_ACT_ERROR 0x01U /* Exit with an error */
+
+
+
+/* End of fragdefs.h */
+
+#endif
+
+
+
#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_CHECKMASK 0x40 /* Mask for check expressions */
-
-/* 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 0x40 /* Check expressions exist */
-
-
-
/* Segment definition */
typedef struct SegDef SegDef;
struct SegDef {
#include "xmalloc.h"
/* ld65 */
-#include "global.h"
+#include "bin.h"
+#include "config.h"
+#include "exports.h"
+#include "expr.h"
#include "error.h"
+#include "global.h"
#include "fileio.h"
#include "lineinfo.h"
#include "segments.h"
-#include "exports.h"
-#include "config.h"
-#include "expr.h"
-#include "bin.h"
+#include "spool.h"
SegDesc* S = N->Seg;
/* Keep the user happy */
- Print (stdout, 1, " Writing `%s'\n", S->Name);
+ Print (stdout, 1, " Writing `%s'\n", GetString (S->Name));
/* Writes do only occur in the load area and not for BSS segments */
DoWrite = (S->Flags & SF_BSS) == 0 && /* No BSS segment */
* in the linker.
*/
Warning ("Segment `%s' in module `%s' requires larger alignment",
- S->Name, GetObjFileName (S->Seg->AlignObj));
+ GetString (S->Name), GetObjFileName (S->Seg->AlignObj));
}
/* Handle ALIGN and OFFSET/START */
-static int BinUnresolved (const char* Name attribute ((unused)), void* D)
+static int BinUnresolved (unsigned Name attribute ((unused)), void* D)
/* Called if an unresolved symbol is encountered */
{
/* Unresolved symbols are an error in binary format. Bump the counter
return 0;
}
-
+
void BinWriteTarget (BinDesc* D, struct File* F)
/* Write a binary output file */
Memory* M;
/* Place the filename in the control structure */
- D->Filename = F->Name;
+ D->Filename = GetString (F->Name);
/* Check for unresolved symbols. The function BinUnresolved is called
* if we get an unresolved symbol.
}
/* Open the file */
- D->F = fopen (F->Name, "wb");
+ D->F = fopen (D->Filename, "wb");
if (D->F == 0) {
- Error ("Cannot open `%s': %s", F->Name, strerror (errno));
+ Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
}
/* Keep the user happy */
- Print (stdout, 1, "Opened `%s'...\n", F->Name);
+ Print (stdout, 1, "Opened `%s'...\n", D->Filename);
/* Dump all memory areas */
M = F->MemList;
while (M) {
- Print (stdout, 1, " Dumping `%s'\n", M->Name);
+ Print (stdout, 1, " Dumping `%s'\n", GetString (M->Name));
BinWriteMem (D, M);
M = M->FNext;
}
/* Close the file */
if (fclose (D->F) != 0) {
- Error ("Cannot write to `%s': %s", F->Name, strerror (errno));
+ Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
}
/* Reset the file and filename */
+
/* */
/* */
/* */
-/* (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 */
/* common */
#include "check.h"
#include "coll.h"
+#include "fragdefs.h"
#include "segdefs.h"
#include "xmalloc.h"
/* ld65 */
+#include "condes.h"
#include "exports.h"
#include "fragment.h"
#include "segments.h"
-#include "condes.h"
+#include "spool.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Struct describing one condes type */
typedef struct ConDesDesc ConDesDesc;
struct ConDesDesc {
- Collection ExpList; /* List of exported symbols */
- char* SegName; /* Name of segment the table is in */
- char* Label; /* Name of table label */
- char* CountSym; /* Name of symbol for entry count */
- unsigned char Order; /* Table order (increasing/decreasing) */
+ Collection ExpList; /* List of exported symbols */
+ unsigned SegName; /* Name of segment the table is in */
+ unsigned Label; /* Name of table label */
+ unsigned CountSym; /* Name of symbol for entry count */
+ unsigned char Order; /* Table order (increasing/decreasing) */
};
/* Array for all types */
static ConDesDesc ConDes[CD_TYPE_COUNT] = {
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
};
Cmp = 1;
} else {
/* Use the name in this case */
- Cmp = strcmp (Exp1->Name, Exp2->Name);
+ Cmp = strcmp (GetString (Exp1->Name), GetString (Exp2->Name));
}
/* Reverse the result for decreasing order */
/* Check if this table has a segment and table label defined. If not,
* creation was not requested in the config file - ignore it.
*/
- if (CD->SegName == 0 || CD->Label == 0) {
+ if (CD->SegName == INVALID_STRING_ID || CD->Label == INVALID_STRING_ID) {
return;
}
/* Define the table start as an export, offset into section is zero
* (the section only contains the table).
*/
- CreateSectionExport (CD->Label, Sec, 0);
+ CreateSectionExport (CD->Label, Sec, 0);
/* If we have a CountSym name given AND if it is referenced, define it
* with the number of elements in the table.
-void ConDesSetSegName (unsigned Type, const char* SegName)
+void ConDesSetSegName (unsigned Type, unsigned SegName)
/* Set the segment name where the table should go */
{
/* Check the parameters */
PRECONDITION (Type <= CD_TYPE_MAX && SegName != 0);
/* Setting the segment name twice is bad */
- CHECK (ConDes[Type].SegName == 0);
+ CHECK (ConDes[Type].SegName == INVALID_STRING_ID);
/* Set the name */
- ConDes[Type].SegName = xstrdup (SegName);
+ ConDes[Type].SegName = SegName;
}
-void ConDesSetLabel (unsigned Type, const char* Name)
+void ConDesSetLabel (unsigned Type, unsigned Name)
/* Set the label for the given ConDes type */
{
/* Check the parameters */
PRECONDITION (Type <= CD_TYPE_MAX && Name != 0);
/* Setting the label twice is bad */
- CHECK (ConDes[Type].Label == 0);
+ CHECK (ConDes[Type].Label == INVALID_STRING_ID);
/* Set the name */
- ConDes[Type].Label = xstrdup (Name);
+ ConDes[Type].Label = Name;
}
-void ConDesSetCountSym (unsigned Type, const char* Name)
+void ConDesSetCountSym (unsigned Type, unsigned Name)
/* Set the name for the given ConDes count symbol */
{
/* Check the parameters */
PRECONDITION (Type <= CD_TYPE_MAX && Name != 0);
/* Setting the symbol twice is bad */
- CHECK (ConDes[Type].CountSym == 0);
+ CHECK (ConDes[Type].CountSym == INVALID_STRING_ID);
/* Set the name */
- ConDes[Type].CountSym = xstrdup (Name);
+ ConDes[Type].CountSym = Name;
}
/* Check the parameters */
PRECONDITION (Type <= CD_TYPE_MAX);
- return (ConDes[Type].SegName != 0);
+ return (ConDes[Type].SegName != INVALID_STRING_ID);
}
/* Check the parameters */
PRECONDITION (Type <= CD_TYPE_MAX);
- return (ConDes[Type].Label != 0);
+ return (ConDes[Type].Label != INVALID_STRING_ID);
}
-
-
/* */
/* */
/* */
-/* (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 */
void ConDesAddExport (struct Export* E);
/* Add the given export to the list of constructors/destructor */
-void ConDesSetSegName (unsigned Type, const char* SegName);
+void ConDesSetSegName (unsigned Type, unsigned SegName);
/* Set the segment name where the table should go */
-void ConDesSetLabel (unsigned Type, const char* Name);
+void ConDesSetLabel (unsigned Type, unsigned Name);
/* Set the label for the given ConDes type */
-void ConDesSetCountSym (unsigned Type, const char* Name);
+void ConDesSetCountSym (unsigned Type, unsigned Name);
/* Set the name for the given ConDes count symbol */
void ConDesSetOrder (unsigned Type, ConDesOrder Order);
-
#include "bin.h"
#include "binfmt.h"
#include "condes.h"
+#include "config.h"
#include "error.h"
#include "exports.h"
#include "global.h"
#include "o65.h"
#include "scanner.h"
-#include "config.h"
+#include "spool.h"
-static File* NewFile (const char* Name);
+static File* NewFile (unsigned Name);
/* Create a new file descriptor and insert it into the list */
-static File* FindFile (const char* Name)
+static File* FindFile (unsigned Name)
/* Find a file with a given name. */
{
File* F = FileList;
while (F) {
- if (strcmp (F->Name, Name) == 0) {
+ if (F->Name == Name) {
return F;
}
F = F->Next;
-static File* GetFile (const char* Name)
+static File* GetFile (unsigned Name)
/* Get a file entry with the given name. Create a new one if needed. */
{
File* F = FindFile (Name);
-static Memory* CfgFindMemory (const char* Name)
+static Memory* CfgFindMemory (unsigned Name)
/* Find the memory are with the given name. Return NULL if not found */
{
Memory* M = MemoryList;
while (M) {
- if (strcmp (M->Name, Name) == 0) {
+ if (M->Name == Name) {
return M;
}
M = M->Next;
-static Memory* CfgGetMemory (const char* Name)
+static Memory* CfgGetMemory (unsigned Name)
/* Find the memory are with the given name. Print an error on an invalid name */
{
Memory* M = CfgFindMemory (Name);
if (M == 0) {
- CfgError ("Invalid memory area `%s'", Name);
+ CfgError ("Invalid memory area `%s'", GetString (Name));
}
return M;
}
-static SegDesc* CfgFindSegDesc (const char* Name)
+static SegDesc* CfgFindSegDesc (unsigned Name)
/* Find the segment descriptor with the given name, return NULL if not found. */
{
SegDesc* S = SegDescList;
while (S) {
- if (strcmp (S->Name, Name) == 0) {
+ if (S->Name == Name) {
/* Found */
return S;
}
-static File* NewFile (const char* Name)
+static File* NewFile (unsigned Name)
/* Create a new file descriptor and insert it into the list */
{
- /* Get the length of the name */
- unsigned Len = strlen (Name);
-
/* Allocate memory */
- File* F = xmalloc (sizeof (File) + Len);
+ File* F = xmalloc (sizeof (File));
/* Initialize the fields */
+ F->Name = Name;
F->Flags = 0;
F->Format = BINFMT_DEFAULT;
F->MemList = 0;
F->MemLast = 0;
- memcpy (F->Name, Name, Len);
- F->Name [Len] = '\0';
/* Insert the struct into the list */
F->Next = FileList;
-static Memory* NewMemory (const char* Name)
+static Memory* NewMemory (unsigned Name)
/* Create a new memory section and insert it into the list */
{
- /* Get the length of the name */
- unsigned Len = strlen (Name);
-
/* Check for duplicate names */
Memory* M = CfgFindMemory (Name);
if (M) {
- CfgError ("Memory area `%s' defined twice", Name);
+ CfgError ("Memory area `%s' defined twice", GetString (Name));
}
/* Allocate memory */
- M = xmalloc (sizeof (Memory) + Len);
+ M = xmalloc (sizeof (Memory));
/* Initialize the fields */
+ M->Name = Name;
M->Next = 0;
M->FNext = 0;
M->Attr = 0;
M->SegList = 0;
M->SegLast = 0;
M->F = 0;
- memcpy (M->Name, Name, Len);
- M->Name [Len] = '\0';
/* Insert the struct into the list */
if (MemoryLast == 0) {
-static SegDesc* NewSegDesc (const char* Name)
+static SegDesc* NewSegDesc (unsigned Name)
/* Create a segment descriptor */
{
Segment* Seg;
- /* Get the length of the name */
- unsigned Len = strlen (Name);
-
/* Check for duplicate names */
SegDesc* S = CfgFindSegDesc (Name);
if (S) {
- CfgError ("Segment `%s' defined twice", Name);
+ CfgError ("Segment `%s' defined twice", GetString (Name));
}
/* Search for the actual segment in the input files. The function may
Seg = SegFind (Name);
/* Allocate memory */
- S = xmalloc (sizeof (SegDesc) + Len);
+ S = xmalloc (sizeof (SegDesc));
/* Initialize the fields */
+ S->Name = Name;
S->Next = 0;
S->Seg = Seg;
S->Attr = 0;
S->Flags = 0;
S->Align = 0;
- memcpy (S->Name, Name, Len);
- S->Name [Len] = '\0';
/* ...and return it */
return S;
while (CfgTok == CFGTOK_IDENT) {
/* Create a new entry on the heap */
- Memory* M = NewMemory (CfgSVal);
+ Memory* M = NewMemory (GetStringId (CfgSVal));
/* Skip the name and the following colon */
CfgNextTok ();
FlagAttr (&M->Attr, MA_FILE, "FILE");
CfgAssureStr ();
/* Get the file entry and insert the memory area */
- FileInsert (GetFile (CfgSVal), M);
+ FileInsert (GetFile (GetStringId (CfgSVal)), M);
break;
case CFGTOK_DEFINE:
* file name.
*/
if ((M->Attr & MA_FILE) == 0) {
- FileInsert (GetFile (OutputName), M);
+ FileInsert (GetFile (GetStringId (OutputName)), M);
}
}
}
CfgAssureStr ();
/* Search for the file, it must exist */
- F = FindFile (CfgSVal);
+ F = FindFile (GetStringId (CfgSVal));
if (F == 0) {
CfgError ("No such file: `%s'", CfgSVal);
}
SegDesc* S;
/* Create a new entry on the heap */
- S = NewSegDesc (CfgSVal);
+ S = NewSegDesc (GetStringId (CfgSVal));
/* Skip the name and the following colon */
CfgNextTok ();
case CFGTOK_LOAD:
FlagAttr (&S->Attr, SA_LOAD, "LOAD");
- S->Load = CfgGetMemory (CfgSVal);
+ S->Load = CfgGetMemory (GetStringId (CfgSVal));
break;
case CFGTOK_OFFSET:
case CFGTOK_RUN:
FlagAttr (&S->Attr, SA_RUN, "RUN");
- S->Run = CfgGetMemory (CfgSVal);
+ S->Run = CfgGetMemory (GetStringId (CfgSVal));
break;
case CFGTOK_START:
if ((S->Flags & SF_RO) == 0) {
if (S->Run->Flags & MF_RO) {
CfgError ("Cannot put r/w segment `%s' in r/o memory area `%s'",
- S->Name, S->Run->Name);
+ GetString (S->Name), GetString (S->Run->Name));
}
}
} else {
/* Print a warning if the segment is not optional */
if ((S->Flags & SF_OPTIONAL) == 0) {
- CfgWarning ("Segment `%s' does not exist", S->Name);
+ CfgWarning ("Segment `%s' does not exist", GetString (S->Name));
}
/* Discard the descriptor */
FreeSegDesc (S);
};
/* Attribute values. */
- char SegName[sizeof (CfgSVal)];
- char Label[sizeof (CfgSVal)];
- char Count[sizeof (CfgSVal)];
+ unsigned SegName = INVALID_STRING_ID;
+ unsigned Label = INVALID_STRING_ID;
+ unsigned Count = INVALID_STRING_ID;
/* Initialize to avoid gcc warnings: */
int Type = -1;
ConDesOrder Order = cdIncreasing;
/* Bitmask to remember the attributes we got already */
enum {
- atNone = 0x0000,
- atSegName = 0x0001,
- atLabel = 0x0002,
- atCount = 0x0004,
- atType = 0x0008,
- atOrder = 0x0010
+ atNone = 0x0000,
+ atSegName = 0x0001,
+ atLabel = 0x0002,
+ atCount = 0x0004,
+ atType = 0x0008,
+ atOrder = 0x0010
};
unsigned AttrFlags = atNone;
/* We expect an identifier */
CfgAssureIdent ();
/* Remember the value for later */
- strcpy (SegName, CfgSVal);
+ SegName = GetStringId (CfgSVal);
break;
case CFGTOK_LABEL:
/* We expect an identifier */
CfgAssureIdent ();
/* Remember the value for later */
- strcpy (Label, CfgSVal);
+ Label = GetStringId (CfgSVal);
break;
case CFGTOK_COUNT:
/* We expect an identifier */
CfgAssureIdent ();
/* Remember the value for later */
- strcpy (Count, CfgSVal);
+ Count = GetStringId (CfgSVal);
break;
case CFGTOK_TYPE:
switch (CfgTok) {
case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
- default: FAIL ("Unexpected type token");
+ default: FAIL ("Unexpected type token");
}
}
break;
long Val;
/* Remember the name */
- char Name [sizeof (CfgSVal)];
- strcpy (Name, CfgSVal);
+ unsigned Name = GetStringId (CfgSVal);
CfgNextTok ();
/* Allow an optional assignment */
{
char Buf [256];
- xsprintf (Buf, sizeof (Buf), "__%s_RUN__", S->Name);
- CreateSegmentExport (Buf, S->Seg, 0);
- xsprintf (Buf, sizeof (Buf), "__%s_SIZE__", S->Name);
- CreateConstExport (Buf, S->Seg->Size);
+ xsprintf (Buf, sizeof (Buf), "__%s_RUN__", GetString (S->Name));
+ CreateSegmentExport (GetStringId (Buf), S->Seg, 0);
+ xsprintf (Buf, sizeof (Buf), "__%s_SIZE__", GetString (S->Name));
+ CreateConstExport (GetStringId (Buf), S->Seg->Size);
S->Flags |= SF_RUN_DEF;
}
{
char Buf [256];
- xsprintf (Buf, sizeof (Buf), "__%s_LOAD__", S->Name);
- CreateMemoryExport (Buf, M, S->Seg->PC - M->Start);
+ xsprintf (Buf, sizeof (Buf), "__%s_LOAD__", GetString (S->Name));
+ CreateMemoryExport (GetStringId (Buf), M, S->Seg->PC - M->Start);
S->Flags |= SF_LOAD_DEF;
}
/* Offset already too large */
if (S->Flags & SF_OFFSET) {
Error ("Offset too small in `%s', segment `%s'",
- M->Name, S->Name);
+ GetString (M->Name), GetString (S->Name));
} else {
Error ("Start address too low in `%s', segment `%s'",
- M->Name, S->Name);
+ GetString (M->Name), GetString (S->Name));
}
}
Addr = NewAddr;
M->FillLevel = Addr + S->Seg->Size - M->Start;
if (M->FillLevel > M->Size) {
Error ("Memory area overflow in `%s', segment `%s' (%lu bytes)",
- M->Name, S->Name, M->FillLevel - M->Size);
+ GetString (M->Name), GetString (S->Name),
+ M->FillLevel - M->Size);
}
/* If requested, define symbols for the start and size of the
* relevant symbols on each walk.
*/
if (S->Load == M) {
- if ((S->Flags & SF_LOAD_DEF) == 0) {
- CreateLoadDefines (M, S);
- } else {
- CHECK ((S->Flags & SF_RUN_DEF) == 0);
- CreateRunDefines (S);
- }
+ if ((S->Flags & SF_LOAD_DEF) == 0) {
+ CreateLoadDefines (M, S);
+ } else {
+ CHECK ((S->Flags & SF_RUN_DEF) == 0);
+ CreateRunDefines (S);
+ }
}
} else {
/* RUN and LOAD in different memory areas, or RUN not
* have only one copy of the segment in the area.
*/
if (S->Run == M) {
- CreateRunDefines (S);
+ CreateRunDefines (S);
}
if (S->Load == M) {
- CreateLoadDefines (M, S);
+ CreateLoadDefines (M, S);
}
}
}
/* If requested, define symbols for start and size of the memory area */
if (M->Flags & MF_DEFINE) {
char Buf [256];
- sprintf (Buf, "__%s_START__", M->Name);
- CreateMemoryExport (Buf, M, 0);
- sprintf (Buf, "__%s_SIZE__", M->Name);
- CreateConstExport (Buf, M->Size);
- sprintf (Buf, "__%s_LAST__", M->Name);
- CreateConstExport (Buf, M->FillLevel);
+ sprintf (Buf, "__%s_START__", GetString (M->Name));
+ CreateMemoryExport (GetStringId (Buf), M, 0);
+ sprintf (Buf, "__%s_SIZE__", GetString (M->Name));
+ CreateConstExport (GetStringId (Buf), M->Size);
+ sprintf (Buf, "__%s_LAST__", GetString (M->Name));
+ CreateConstExport (GetStringId (Buf), M->FillLevel);
}
/* Next memory area */
if (F->MemList) {
/* Is there an output file? */
- if (strlen (F->Name) > 0) {
+ if (strlen (GetString (F->Name)) > 0) {
/* Assign a proper binary format */
if (F->Format == BINFMT_DEFAULT) {
switch (F->Format) {
case BINFMT_BINARY:
- BinWriteTarget (BinFmtDesc, F);
- break;
+ BinWriteTarget (BinFmtDesc, F);
+ break;
case BINFMT_O65:
- O65WriteTarget (O65FmtDesc, F);
- break;
+ O65WriteTarget (O65FmtDesc, F);
+ break;
default:
Internal ("Invalid binary format: %u", F->Format);
MemListNode* N;
/* Debugging */
- Print (stdout, 2, "Skipping `%s'...\n", M->Name);
+ Print (stdout, 2, "Skipping `%s'...\n", GetString (M->Name));
/* Walk throught the segments */
N = M->SegList;
while (N) {
- if (N->Seg->Load == M) {
- /* Load area - mark the segment as dumped */
- N->Seg->Seg->Dumped = 1;
- }
+ if (N->Seg->Load == M) {
+ /* Load area - mark the segment as dumped */
+ N->Seg->Seg->Dumped = 1;
+ }
- /* Next segment node */
- N = N->Next;
+ /* Next segment node */
+ N = N->Next;
}
/* Next memory area */
M = M->FNext;
/* File list entry */
typedef struct File File;
struct File {
+ unsigned Name; /* Name index of the file */
File* Next; /* Pointer to next entry in list */
unsigned Flags;
unsigned Format; /* Output format */
struct Memory* MemList; /* List of memory areas in this file */
struct Memory* MemLast; /* Last memory area in this file */
- char Name [1]; /* Name of file */
};
/* Segment list node. Needed because there are two lists (RUN & LOAD) */
/* Memory list entry */
typedef struct Memory Memory;
struct Memory {
+ unsigned Name; /* Name index of the memory section */
Memory* Next; /* Pointer to next entry in list */
Memory* FNext; /* Next in file list */
unsigned Attr; /* Which values are valid? */
MemListNode* SegList; /* List of segments for this section */
MemListNode* SegLast; /* Last segment in this section */
File* F; /* File that contains the entry */
- char Name [1]; /* Name of the memory section */
};
/* Segment descriptor entry */
typedef struct SegDesc SegDesc;
struct SegDesc {
+ unsigned Name; /* Index of the name */
SegDesc* Next; /* Pointer to next entry in list */
- Segment* Seg; /* Pointer to segment structure */
- unsigned Attr; /* Attributes for segment */
- unsigned Flags; /* Set of bitmapped flags */
+ Segment* Seg; /* Pointer to segment structure */
+ unsigned Attr; /* Attributes for segment */
+ unsigned Flags; /* Set of bitmapped flags */
Memory* Load; /* Load memory section */
- Memory* Run; /* Run memory section */
+ Memory* Run; /* Run memory section */
unsigned long Addr; /* Start address or offset into segment */
unsigned char Align; /* Alignment if given */
- char Name [1]; /* Copy of name */
};
/* Segment list */
#include <string.h>
-/* common */
+/* common */
#include "check.h"
#include "symdefs.h"
#include "xmalloc.h"
/* ld65 */
-#include "global.h"
+#include "dbgsyms.h"
#include "error.h"
+#include "expr.h"
#include "fileio.h"
+#include "global.h"
#include "objdata.h"
-#include "expr.h"
-#include "dbgsyms.h"
+#include "spool.h"
((Val >> 0) & 0xFF);
/* Check for this symbol */
- DbgSym* Sym = DbgSymPool [Hash];
+ DbgSym* Sym = DbgSymPool[Hash];
while (Sym) {
/* Is this symbol identical? */
- if (strcmp (Sym->Name, D->Name) == 0 && EqualExpr (Sym->Expr, D->Expr)) {
+ if (Sym->Name == D->Name && EqualExpr (Sym->Expr, D->Expr)) {
/* Found */
return Sym;
}
D = NewDbgSym (Type, O);
/* Read and assign the name */
- D->Name = GetObjString (O, ReadVar (F));
+ D->Name = MakeGlobalStringId (O, ReadVar (F));
/* Read the value */
if (IS_EXP_EXPR (Type)) {
if (GetDbgSym (D, Val) == 0) {
/* Emit the VICE label line */
- fprintf (F, "al %06lX .%s\n", Val, D->Name);
+ fprintf (F, "al %06lX .%s\n", Val, GetString (D->Name));
/* Insert the symbol into the table */
InsertDbgSym (D, Val);
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 Name; /* Name */
unsigned char Type; /* Type of symbol */
};
-
-
/* ld65 */
#include "condes.h"
#include "error.h"
+#include "exports.h"
+#include "expr.h"
#include "fileio.h"
#include "global.h"
#include "objdata.h"
-#include "expr.h"
-#include "exports.h"
+#include "spool.h"
/* Hash table */
-#define HASHTAB_SIZE 4081
-static Export* HashTab [HASHTAB_SIZE];
+#define HASHTAB_MASK 0x0FFFU
+#define HASHTAB_SIZE (HASHTAB_MASK + 1)
+static Export* HashTab[HASHTAB_SIZE];
/* Import management variables */
static unsigned ImpCount = 0; /* Import count */
-static Export* NewExport (unsigned char Type, const char* Name, ObjData* Obj);
+static Export* NewExport (unsigned char Type, unsigned Name, ObjData* Obj);
/* Create a new export and initialize it */
/* Initialize the fields */
I->Next = 0;
I->Obj = Obj;
- I->V.Name = 0;
+ I->Exp = 0;
+ I->Name = INVALID_STRING_ID;
I->Type = Type;
/* Return the new structure */
/* Insert an import into the table */
{
Export* E;
- unsigned HashVal;
/* As long as the import is not inserted, V.Name is valid */
- const char* Name = I->V.Name;
+ unsigned Name = I->Name;
/* Create a hash value for the given name */
- HashVal = HashStr (Name) % HASHTAB_SIZE;
+ unsigned Hash = (Name & HASHTAB_MASK);
/* Search through the list in that slot and print matching duplicates */
- if (HashTab [HashVal] == 0) {
+ if (HashTab[Hash] == 0) {
/* The slot is empty, we need to insert a dummy export */
- E = HashTab [HashVal] = NewExport (0, Name, 0);
+ E = HashTab[Hash] = NewExport (0, Name, 0);
++ExpCount;
} else {
- E = HashTab [HashVal];
+ E = HashTab [Hash];
while (1) {
- if (strcmp (E->Name, Name) == 0) {
+ if (E->Name == Name) {
/* We have an entry, L points to it */
- break;
+ break;
}
if (E->Next == 0) {
/* End of list an entry not found, insert a dummy */
/* Ok, E now points to a valid exports entry for the given import. Insert
* the import into the imports list and update the counters.
*/
- I->V.Exp = E;
+ I->Exp = E;
I->Next = E->ImpList;
E->ImpList = I;
E->ImpCount++;
I = NewImport (Type, Obj);
/* Read the name */
- I->V.Name = GetObjString (Obj, ReadVar (F));
+ I->Name = MakeGlobalStringId (Obj, ReadVar (F));
/* Read the file position */
ReadFilePos (F, &I->Pos);
-static Export* NewExport (unsigned char Type, const char* Name, ObjData* Obj)
+static Export* NewExport (unsigned char Type, unsigned Name, ObjData* Obj)
/* Create a new export and initialize it */
{
/* Allocate memory */
Export* E = xmalloc (sizeof (Export));
/* Initialize the fields */
+ E->Name = Name;
E->Next = 0;
E->Flags = 0;
E->Obj = Obj;
E->Expr = 0;
E->Type = Type;
memset (E->ConDes, 0, sizeof (E->ConDes));
- if (Name) {
- E->Name = xstrdup (Name);
- } else {
- /* Name will get added later */
- E->Name = 0;
- }
/* Return the new entry */
return E;
Export* L;
Export* Last;
Import* Imp;
- unsigned HashVal;
+ unsigned Hash;
/* Insert the export into any condes tables if needed */
if (IS_EXP_CONDES (E->Type)) {
}
/* Create a hash value for the given name */
- HashVal = HashStr (E->Name) % HASHTAB_SIZE;
+ Hash = (E->Name & HASHTAB_MASK);
/* Search through the list in that slot */
- if (HashTab [HashVal] == 0) {
+ if (HashTab[Hash] == 0) {
/* The slot is empty */
- HashTab [HashVal] = E;
+ HashTab[Hash] = E;
++ExpCount;
} else {
Last = 0;
- L = HashTab [HashVal];
+ L = HashTab[Hash];
do {
- if (strcmp (L->Name, E->Name) == 0) {
- /* This may be an unresolved external */
- if (L->Expr == 0) {
-
- /* This *is* an unresolved external */
- E->Next = L->Next;
- E->ImpCount = L->ImpCount;
- E->ImpList = L->ImpList;
+ if (L->Name == E->Name) {
+ /* This may be an unresolved external */
+ if (L->Expr == 0) {
+
+ /* This *is* an unresolved external */
+ E->Next = L->Next;
+ E->ImpCount = L->ImpCount;
+ E->ImpList = L->ImpList;
if (Last) {
Last->Next = E;
} else {
- HashTab [HashVal] = E;
+ HashTab[Hash] = E;
}
ImpOpen -= E->ImpCount; /* Decrease open imports now */
xfree (L);
*/
Imp = E->ImpList;
while (Imp) {
- Imp->V.Exp = E;
+ Imp->Exp = E;
Imp = Imp->Next;
}
} else {
/* Duplicate entry, ignore it */
- Warning ("Duplicate external identifier: `%s'", L->Name);
+ Warning ("Duplicate external identifier: `%s'",
+ GetString (L->Name));
}
return;
}
Type = Read8 (F);
/* Create a new export without a name */
- E = NewExport (Type, 0, O);
+ E = NewExport (Type, INVALID_STRING_ID, O);
/* Read the constructor/destructor decls if we have any */
ConDesCount = GET_EXP_CONDES_COUNT (Type);
}
/* Read the name */
- E->Name = GetObjString (O, ReadVar (F));
+ E->Name = MakeGlobalStringId (O, ReadVar (F));
/* Read the value */
if (IS_EXP_EXPR (Type)) {
-Export* CreateConstExport (const char* Name, long Value)
+Export* CreateConstExport (unsigned Name, long Value)
/* Create an export for a literal date */
{
/* Create a new export */
-Export* CreateMemoryExport (const char* Name, Memory* Mem, unsigned long Offs)
+Export* CreateMemoryExport (unsigned Name, Memory* Mem, unsigned long Offs)
/* Create an relative export for a memory area offset */
{
/* Create a new export */
-Export* CreateSegmentExport (const char* Name, Segment* Seg, unsigned long Offs)
+Export* CreateSegmentExport (unsigned Name, Segment* Seg, unsigned long Offs)
/* Create a relative export to a segment */
{
/* Create a new export */
-Export* CreateSectionExport (const char* Name, Section* Sec, unsigned long Offs)
+Export* CreateSectionExport (unsigned Name, Section* Sec, unsigned long Offs)
/* Create a relative export to a section */
{
/* Create a new export */
-Export* FindExport (const char* Name)
+Export* FindExport (unsigned Name)
/* Check for an identifier in the list. Return 0 if not found, otherwise
* return a pointer to the export.
*/
{
/* Get a pointer to the list with the symbols hash value */
- Export* L = HashTab [HashStr (Name) % HASHTAB_SIZE];
+ Export* L = HashTab[Name & HASHTAB_MASK];
while (L) {
/* Search through the list in that slot */
- if (strcmp (L->Name, Name) == 0) {
+ if (L->Name == Name) {
/* Entry found */
return L;
}
-int IsUnresolved (const char* Name)
+int IsUnresolved (unsigned Name)
/* Check if this symbol is an unresolved export */
{
/* Find the export */
{
if (E->Expr == 0) {
/* OOPS */
- Internal ("`%s' is an undefined external", E->Name);
+ Internal ("`%s' is an undefined external", GetString (E->Name));
}
return GetExprVal (E->Expr);
}
/* User defined export */
Warning ("Type mismatch for `%s', export in "
"%s(%lu), import in %s(%lu)",
- E->Name, GetSourceFileName (E->Obj, Imp->Pos.Name),
- E->Pos.Line, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
+ GetString (E->Name),
+ GetSourceFileName (E->Obj, Imp->Pos.Name),
+ 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)",
- E->Name, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
+ GetString (E->Name),
+ GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
}
}
Import* Imp = E->ImpList;
fprintf (stderr,
"Unresolved external `%s' referenced in:\n",
- E->Name);
+ GetString (E->Name));
while (Imp) {
const char* Name = GetSourceFileName (Imp->Obj, Imp->Pos.Name);
fprintf (stderr, " %s(%lu)\n", Name, Imp->Pos.Line);
static int CmpExpName (const void* K1, const void* K2)
/* Compare function for qsort */
{
- return strcmp ((*(Export**)K1)->Name, (*(Export**)K2)->Name);
+ return strcmp (GetString ((*(Export**)K1)->Name),
+ GetString ((*(Export**)K2)->Name));
}
/* Walk through the list and insert the exports */
for (I = 0, J = 0; I < sizeof (HashTab) / sizeof (HashTab [0]); ++I) {
- Export* E = HashTab [I];
+ Export* E = HashTab[I];
while (E) {
CHECK (J < ExpCount);
- ExpPool [J++] = E;
+ ExpPool[J++] = E;
E = E->Next;
}
}
if (VerboseMap || E->ImpCount > 0 || IS_EXP_CONDES (E->Type)) {
fprintf (F,
"%-25s %06lX %c%c%c%c ",
- E->Name,
+ GetString (E->Name),
GetExportVal (E),
E->ImpCount? 'R' : ' ',
IS_EXP_LABEL (E->Type)? 'L' : 'E',
/* Print the export */
fprintf (F,
"%s (%s):\n",
- Exp->Name,
+ GetString (Exp->Name),
GetObjFileName (Exp->Obj));
/* Print all imports for this symbol */
/* Print all exports */
for (I = 0; I < ExpCount; ++I) {
const Export* E = ExpPool [I];
- fprintf (F, "al %06lX .%s\n", GetExportVal (E), E->Name);
+ fprintf (F, "al %06lX .%s\n", GetExportVal (E), GetString (E->Name));
}
}
/* Print an error about a circular reference using to define the given export */
{
Error ("Circular reference for symbol `%s', %s(%lu)",
- E->Name, GetSourceFileName (E->Obj, E->Pos.Name), E->Pos.Line);
+ GetString (E->Name),
+ GetSourceFileName (E->Obj, E->Pos.Name),
+ E->Pos.Line);
}
+
Import* Next; /* Single linked list */
ObjData* Obj; /* Object file that imports the name */
FilePos Pos; /* File position of reference */
- union {
- struct Export* Exp; /* Matching export for this import */
- const char* Name; /* Name if not in table */
- } V;
+ struct Export* Exp; /* Matching export for this import */
+ unsigned Name; /* Name if not in table */
unsigned char Type; /* Type of import */
};
/* Export symbol structure */
typedef struct Export Export;
struct Export {
+ unsigned Name; /* Name */
Export* Next; /* Hash table link */
unsigned Flags; /* Generic flags */
ObjData* Obj; /* Object file that exports the name */
ExprNode* Expr; /* Expression (0 if not def'd) */
unsigned char Type; /* Type of export */
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
- const char* Name; /* Name */
};
* resolved, or a value != zero if the symbol could be resolved. The
* CheckExports routine will print out the missing symbol in the first case.
*/
-typedef int (*ExpCheckFunc) (const char* Name, void* Data);
+typedef int (*ExpCheckFunc) (unsigned Name, void* Data);
void InsertExport (Export* E);
/* Insert an exported identifier and check if it's already in the list */
-Export* CreateConstExport (const char* Name, long Value);
+Export* CreateConstExport (unsigned Name, long Value);
/* Create an export for a literal date */
-Export* CreateMemoryExport (const char* Name, Memory* Mem, unsigned long Offs);
+Export* CreateMemoryExport (unsigned Name, Memory* Mem, unsigned long Offs);
/* Create an relative export for a memory area offset */
-Export* CreateSegmentExport (const char* Name, Segment* Seg, unsigned long Offs);
+Export* CreateSegmentExport (unsigned Name, Segment* Seg, unsigned long Offs);
/* Create a relative export to a segment */
-Export* CreateSectionExport (const char* Name, Section* S, unsigned long Offs);
+Export* CreateSectionExport (unsigned Name, Section* S, unsigned long Offs);
/* Create a relative export to a section */
-Export* FindExport (const char* Name);
+Export* FindExport (unsigned Name);
/* Check for an identifier in the list. Return 0 if not found, otherwise
* return a pointer to the export.
*/
-int IsUnresolved (const char* Name);
+int IsUnresolved (unsigned Name);
/* Check if this symbol is an unresolved export */
int IsUnresolvedExport (const Export* E);
+
/* */
/* */
/* */
-/* (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 */
* which in turn means, that we have a circular reference.
*/
if (ExportHasMark (E)) {
- Error ("Circular reference for symbol `%s', %s(%lu)",
- E->Name, GetSourceFileName (E->Obj, E->Pos.Name),
- E->Pos.Line);
+ CircularRefError (E);
Const = 0;
} else {
MarkExport (E);
PRECONDITION (Expr->Op == EXPR_SYMBOL);
/* Return the export */
- return Expr->Obj->Imports [Expr->V.ImpNum]->V.Exp;
+ return Expr->Obj->Imports [Expr->V.ImpNum]->Exp;
}
/* Not a leaf node */
Expr->Left = ReadExpr (F, O);
- Expr->Right = ReadExpr (F, O);
+ Expr->Right = ReadExpr (F, O);
}
/* common */
-#include "segdefs.h"
+#include "fragdefs.h"
#include "xmalloc.h"
/* ld65 */
-#include "segments.h"
+#include "error.h"
+#include "expr.h"
#include "fragment.h"
+#include "fileio.h"
+#include "segments.h"
+#include "spool.h"
+static FragCheck* NewFragCheck (unsigned Action)
+/* Allocate a new FragCheck struct and return it */
+{
+ /* Allocate memory */
+ FragCheck* FC = xmalloc (sizeof (FragCheck));
+
+ /* Initialize the fields */
+ FC->Next = 0;
+ FC->Expr = 0;
+ FC->Action = Action;
+ FC->Message = INVALID_STRING_ID;
+
+ /* Return the new struct */
+ return FC;
+}
+
+
+
+FragCheck* ReadFragCheck (FILE* F, Fragment* Frag)
+/* Read a fragment check expression from the given file */
+{
+ /* Get the object file pointer from the fragment */
+ ObjData* O = Frag->Obj;
+
+ /* Read the action and create a new struct */
+ FragCheck* FC = NewFragCheck (ReadVar (F));
+
+ /* Determine the remaining data from the action */
+ switch (FC->Action) {
+
+ case FRAG_ACT_WARN:
+ case FRAG_ACT_ERROR:
+ FC->Expr = ReadExpr (F, O);
+ FC->Message = MakeGlobalStringId (O, ReadVar (F));
+ break;
+
+ default:
+ Internal ("In module `%s', file `%s', line %lu: Invalid fragment "
+ "check action: %u",
+ GetObjFileName (O),
+ GetSourceFileName (O, Frag->Pos.Name),
+ Frag->Pos.Line, FC->Action);
+ }
+
+ /* Return the new fragment check */
+ return FC;
+}
+
+
+
Fragment* NewFragment (unsigned char Type, unsigned Size, Section* S)
/* Create a new fragment and insert it into the section S */
{
struct LineInfo;
+struct ObjData;
struct Section;
/* Fragment check expression */
-typedef struct CheckExpr CheckExpr;
-struct CheckExpr {
- struct CheckExpr* Next; /* Next check expression */
+typedef struct FragCheck FragCheck;
+struct FragCheck {
+ struct FragCheck* Next; /* Next check expression */
struct ExprNode* Expr; /* The expression itself */
unsigned Action; /* Action to take if the check fails */
unsigned Message; /* Message number */
struct ObjData* Obj; /* Source of fragment */
unsigned Size; /* Size of data/expression */
struct ExprNode* Expr; /* Expression if FRAG_EXPR */
- FilePos Pos; /* File position in source */
+ FilePos Pos; /* File position in source */
struct LineInfo* LI; /* Additional line info */
- CheckExpr* Check; /* Single linked list of expressions */
+ FragCheck* Check; /* Single linked list of checks */
unsigned char Type; /* Type of fragment */
unsigned char LitBuf [1]; /* Dynamically alloc'ed literal buffer */
};
+FragCheck* ReadFragCheck (FILE* F, Fragment* Frag);
+/* Read a fragment check expression from the given file */
+
Fragment* NewFragment (unsigned char Type, unsigned Size, struct Section* S);
/* Create a new fragment and insert it into the section S */
/* We have the data now */
O->Flags |= OBJ_HAVEDATA;
-
}
+ /* All references to strings are now resolved, so we can delete
+ * the module string pool.
+ */
+ FreeObjStrings (O);
+
/* Add a pointer to the library name */
O->LibName = LibName;
}
#include "objfile.h"
#include "scanner.h"
#include "segments.h"
+#include "spool.h"
#include "tgtcfg.h"
/* Initialize the input file search paths */
InitSearchPaths ();
+ /* Initialize the string pool */
+ InitStrPool ();
+
/* Check the parameters */
I = 1;
while (I < ArgCount) {
/* */
/* */
/* */
-/* (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 */
/* */
/* */
#include <string.h>
#include <errno.h>
-#include "global.h"
-#include "error.h"
-#include "objdata.h"
-#include "segments.h"
+/* ld65 */
+#include "config.h"
#include "dbginfo.h"
#include "dbgsyms.h"
#include "exports.h"
-#include "config.h"
+#include "global.h"
+#include "error.h"
#include "mapfile.h"
+#include "objdata.h"
+#include "segments.h"
+#include "spool.h"
*/
if (VerboseMap || S->Size > 0) {
fprintf (F, " %-15s Offs = %06lX Size = %06lX\n",
- S->Seg->Name, S->Offs, S->Size);
+ GetString (S->Seg->Name), S->Offs, S->Size);
}
}
}
/* */
/* */
/* */
-/* (C) 1999-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 */
/* */
/* */
#include "global.h"
#include "lineinfo.h"
#include "o65.h"
+#include "spool.h"
ExtSymTab* Imports; /* Table with imported symbols */
unsigned Undef; /* Count of undefined symbols */
FILE* F; /* The file we're writing to */
- char* Filename; /* Name of the output file */
+ const char* Filename; /* Name of the output file */
O65RelocTab* TextReloc; /* Relocation table for text segment */
O65RelocTab* DataReloc; /* Relocation table for data segment */
CircularRefError (E);
} else if (E->Expr == 0) {
/* Dummy export, must be an o65 imported symbol */
- ExtSym* S = O65GetImport (D->D, E->Name);
+ ExtSym* S = O65GetImport (D->D, GetString (E->Name));
CHECK (S != 0);
if (D->ExtRef) {
/* We cannot have more than one external reference in o65 */
S = Seg [I];
/* Keep the user happy */
- Print (stdout, 1, " Writing `%s'\n", S->Name);
+ Print (stdout, 1, " Writing `%s'\n", GetString (S->Name));
/* Write this segment */
if (DoWrite) {
* export does really exist, so if it is unresolved, or if we don't
* find it, there is an error in the linker code.
*/
- Export* E = FindExport (Name);
+ Export* E = FindExport (GetStringId (Name));
if (E == 0 || IsUnresolvedExport (E)) {
Internal ("Unresolved export `%s' found in O65WriteExports", Name);
}
/* Get the export for this symbol and check if it does exist and is
* a resolved symbol.
*/
- Export* E = FindExport (Ident);
+ Export* E = FindExport (GetStringId (Ident));
if (E == 0 || IsUnresolvedExport (E)) {
Error ("Unresolved export: `%s'", Ident);
}
-static int O65Unresolved (const char* Name, void* D)
+static int O65Unresolved (unsigned Name, void* D)
/* Called if an unresolved symbol is encountered */
{
/* Check if the symbol is an imported o65 symbol */
- if (O65GetImport (D, Name) != 0) {
+ if (O65GetImport (D, GetString (Name)) != 0) {
/* This is an external symbol, relax... */
return 1;
} else {
time_t T;
/* Place the filename in the control structure */
- D->Filename = F->Name;
+ D->Filename = GetString (F->Name);
/* Check for unresolved symbols. The function O65Unresolved is called
* if we get an unresolved symbol.
O65SetupHeader (D);
/* Open the file */
- D->F = fopen (F->Name, "wb");
+ D->F = fopen (D->Filename, "wb");
if (D->F == 0) {
- Error ("Cannot open `%s': %s", F->Name, strerror (errno));
+ Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
}
/* Keep the user happy */
- Print (stdout, 1, "Opened `%s'...\n", F->Name);
+ Print (stdout, 1, "Opened `%s'...\n", D->Filename);
/* Define some more options: A timestamp and the linker version */
T = time (0);
/* Close the file */
if (fclose (D->F) != 0) {
- Error ("Cannot write to `%s': %s", F->Name, strerror (errno));
+ Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
}
/* Reset the file and filename */
+
#include "error.h"
#include "fileinfo.h"
#include "objdata.h"
+#include "spool.h"
-const char* GetObjString (const ObjData* O, unsigned long Index)
+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.
+ */
+{
+ while (O->StringCount) {
+ xfree (O->Strings[--O->StringCount]);
+ }
+ xfree (O->Strings);
+ O->Strings = 0;
+}
+
+
+
+const char* GetObjString (const ObjData* O, unsigned Index)
/* Get a string from the object file string table. Abort if the string index
* is invalid.
*/
{
if (Index >= O->StringCount) {
- Error ("Invalid string index (%lu) in module `%s'",
+ Error ("Invalid string index (%u) in module `%s'",
Index, GetObjFileName (O));
}
return O->Strings[Index];
+unsigned MakeGlobalStringId (const ObjData* O, unsigned Index)
+/* Convert a local string id into a global one and return it. */
+{
+ if (Index >= O->StringCount) {
+ Error ("Invalid string index (%u) in module `%s'",
+ Index, GetObjFileName (O));
+ }
+ return GetStringId (O->Strings[Index]);
+}
+
+
+
const char* GetObjFileName (const ObjData* O)
/* Get the name of the object file. Return "[linker generated]" if the object
* file is NULL.
ObjData* NewObjData (void);
/* Allocate a new structure on the heap, insert it into the list, return it */
-const char* GetObjString (const ObjData* O, unsigned long Index);
+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.
+ */
+
+const char* GetObjString (const ObjData* O, unsigned Index);
/* Get a string from the object file string table. Abort if the string index
* is invalid.
*/
+unsigned MakeGlobalStringId (const ObjData* O, unsigned Index);
+/* Convert a local string id into a global one and return it. */
+
const char* GetObjFileName (const ObjData* O);
/* Get the name of the object file. Return "[linker generated]" if the object
* file is NULL.
/* Done, close the file (we read it only, so no error check) */
fclose (Obj);
+
+ /* All references to strings are now resolved, so we can delete the module
+ * string pool.
+ */
+ FreeObjStrings (O);
}
/* common */
#include "check.h"
#include "exprdefs.h"
+#include "fragdefs.h"
#include "hashstr.h"
#include "print.h"
#include "segdefs.h"
#include "global.h"
#include "lineinfo.h"
#include "segments.h"
+#include "spool.h"
/* Hash table */
-#define HASHTAB_SIZE 253
+#define HASHTAB_MASK 0x3FU
+#define HASHTAB_SIZE (HASHTAB_MASK + 1)
static Segment* HashTab [HASHTAB_SIZE];
static unsigned SegCount = 0; /* Segment count */
-static Segment* SegFindInternal (const char* Name, unsigned HashVal)
-/* Try to find the segment with the given name, return a pointer to the
- * segment structure, or 0 if not found.
- */
-{
- Segment* S = HashTab [HashVal];
- while (S) {
- if (strcmp (Name, S->Name) == 0) {
- /* Found */
- break;
- }
- S = S->Next;
- }
- /* Not found */
- return S;
-}
-
-
-
-static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Type)
+static Segment* NewSegment (unsigned Name, unsigned char Type)
/* Create a new segment and initialize it */
{
- /* Get the length of the symbol name */
- unsigned Len = strlen (Name);
+ unsigned Hash;
/* Allocate memory */
- Segment* S = xmalloc (sizeof (Segment) + Len);
+ Segment* S = xmalloc (sizeof (Segment));
/* Initialize the fields */
+ S->Name = Name;
S->Next = 0;
S->SecRoot = 0;
S->SecLast = 0;
S->FillVal = 0;
S->Type = Type;
S->Dumped = 0;
- memcpy (S->Name, Name, Len);
- S->Name [Len] = '\0';
/* Insert the segment into the segment list */
S->List = SegRoot;
++SegCount;
/* Insert the segment into the segment hash list */
- S->Next = HashTab [HashVal];
- HashTab [HashVal] = S;
+ Hash = (S->Name & HASHTAB_MASK);
+ S->Next = HashTab[Hash];
+ HashTab[Hash] = S;
/* Return the new entry */
return S;
-Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName)
+Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName)
/* Search for a segment and return an existing one. If the segment does not
* exist, create a new one and return that. ObjName is only used for the error
* message and may be NULL if the segment is linker generated.
*/
{
- /* Create a hash over the name and try to locate the segment in the table */
- unsigned HashVal = HashStr (Name) % HASHTAB_SIZE;
- Segment* S = SegFindInternal (Name, HashVal);
+ /* Try to locate the segment in the table */
+ Segment* S = SegFind (Name);
/* If we don't have that segment already, allocate it using the type of
* the first section.
*/
if (S == 0) {
/* Create a new segment */
- S = NewSegment (Name, HashVal, Type);
+ S = NewSegment (Name, Type);
} else {
/* Check if the existing segment has the requested type */
if (S->Type != Type) {
if (ObjName == 0) {
ObjName = "[linker generated]";
}
- Error ("Module `%s': Type mismatch for segment `%s'", ObjName, Name);
+ Error ("Module `%s': Type mismatch for segment `%s'", ObjName,
+ GetString (Name));
}
}
/* Allocate memory */
- Section* S = xmalloc (sizeof (Segment));
+ Section* S = xmalloc (sizeof (Section));
/* Initialize the data */
S->Next = 0;
Section* ReadSection (FILE* F, ObjData* O)
/* Read a section from a file */
{
- char* Name;
+ unsigned Name;
unsigned Size;
unsigned char Align;
unsigned char Type;
/* Read the segment data */
(void) Read32 (F); /* File size of data */
- Name = ReadStr (F); /* Segment name */
+ Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */
Size = Read32 (F); /* Size of data */
Align = Read8 (F); /* Alignment */
Type = Read8 (F); /* Segment type */
/* Print some data */
Print (stdout, 2, "Module `%s': Found segment `%s', size = %u, align = %u, type = %u\n",
- GetObjFileName (O), Name, Size, Align, Type);
+ GetObjFileName (O), GetString (Name), Size, Align, Type);
/* Get the segment for this section */
S = GetSegment (Name, Type, GetObjFileName (O));
- /* We have the segment and don't need the name any longer */
- xfree (Name);
-
/* Allocate the section we will return later */
Sec = NewSection (S, Align, Type);
default:
Error ("Unknown fragment type in module `%s', segment `%s': %02X",
- GetObjFileName (O), S->Name, Type);
+ GetObjFileName (O), GetString (S->Name), Type);
/* NOTREACHED */
return 0;
}
unsigned Count = ReadVar (F);
/* Read the expressions */
- CheckExpr* Last = 0;
while (Count--) {
/* ### */
}
-Segment* SegFind (const char* Name)
+Segment* SegFind (unsigned Name)
/* Return the given segment or NULL if not found. */
{
- return SegFindInternal (Name, HashStr (Name) % HASHTAB_SIZE);
+ Segment* S = HashTab[Name & HASHTAB_MASK];
+ while (S) {
+ if (Name == S->Name) {
+ /* Found */
+ break;
+ }
+ S = S->Next;
+ }
+ /* Not found */
+ return S;
}
Segment* Seg = SegRoot;
while (Seg) {
Section* S = Seg->SecRoot;
- printf ("Segment: %s (%lu)\n", Seg->Name, Seg->Size);
+ printf ("Segment: %s (%lu)\n", GetString (Seg->Name), Seg->Size);
while (S) {
Fragment* F = S->FragRoot;
printf (" Section:\n");
case FRAG_FILL:
printf (" Empty space (%u bytes)\n", F->Size);
break;
-
+
default:
Internal ("Invalid fragment type: %02X", F->Type);
}
return -1;
} else {
/* Sort segments with equal starts by name */
- return strcmp (S1->Name, S2->Name);
+ return strcmp (GetString (S1->Name), GetString (S2->Name));
}
}
--End;
}
fprintf (F, "%-20s %06lX %06lX %06lX\n",
- S->Name, S->PC, End, S->Size);
+ GetString (S->Name), S->PC, End, S->Size);
}
}
Segment* S = SegRoot;
while (S) {
if (S->Size > 0 && S->Dumped == 0) {
- Error ("Missing memory area assignment for segment `%s'", S->Name);
+ Error ("Missing memory area assignment for segment `%s'",
+ GetString (S->Name));
}
S = S->List;
}
/* Segment structure */
typedef struct Segment Segment;
struct Segment {
+ unsigned Name; /* Name index of the segment */
Segment* Next; /* Hash list */
Segment* List; /* List of all segments */
struct Section* SecRoot; /* Section list */
unsigned char FillVal; /* Value to use for fill bytes */
unsigned char Type; /* Type of segment */
char Dumped; /* Did we dump this segment? */
- char Name [1]; /* Name, dynamically allocated */
};
-Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName);
+Segment* GetSegment (unsigned Name, unsigned char Type, const char* ObjName);
/* Search for a segment and return an existing one. If the segment does not
* exist, create a new one and return that. ObjName is only used for the error
* message and may be NULL if the segment is linker generated.
Section* ReadSection (FILE* F, struct ObjData* O);
/* Read a section from a file */
-Segment* SegFind (const char* Name);
+Segment* SegFind (unsigned Name);
/* Return the given segment or NULL if not found. */
int IsBSSType (Segment* S);
#endif
-
+
+void InitStrPool (void)
+/* Initialize the string pool */
+{
+ /* We insert a first string here, which will have id zero. This means
+ * that we can treat index zero later as invalid.
+ */
+ SP_Add (&StrPool, "<invalid message #0>");
+}
+
+
+
+
+/* An invalid message index */
+#define INVALID_STRING_ID 0U
+
+/* The string pool we're using */
extern StringPool StrPool;
# define GetStringId(S) SP_Add (&StrPool, (S))
#endif
+#if defined(HAVE_INLINE)
+INLINE const char* GetString (unsigned Index)
+/* Convert a string index into a string */
+{
+ return SP_Get (&StrPool, Index);
+}
+#else
+# define GetString(Index) SP_Get (&StrPool, (Index))
+#endif
+
+void InitStrPool (void);
+/* Initialize the string pool */
+
/* End of spool.h */