O->Strings[I] = ReadStr (Lib);
}
- /* Exports */
- O->ExportSize = ReadVar (Lib);
- O->Exports = xmalloc (O->ExportSize);
- ReadData (Lib, O->Exports, O->ExportSize);
-
/* Imports */
O->ImportSize = ReadVar (Lib);
O->Imports = xmalloc (O->ImportSize);
ReadData (Lib, O->Imports, O->ImportSize);
+
+ /* Exports */
+ O->ExportSize = ReadVar (Lib);
+ O->Exports = xmalloc (O->ExportSize);
+ ReadData (Lib, O->Exports, O->ExportSize);
}
WriteStr (NewLib, O->Strings[I]);
}
- /* Exports */
- WriteVar (NewLib, O->ExportSize);
- WriteData (NewLib, O->Exports, O->ExportSize);
-
/* Imports */
WriteVar (NewLib, O->ImportSize);
WriteData (NewLib, O->Imports, O->ImportSize);
+
+ /* Exports */
+ WriteVar (NewLib, O->ExportSize);
+ WriteData (NewLib, O->Exports, O->ExportSize);
}
long IVal; /* If this is a int value */
struct SymEntry* Sym; /* If this is a symbol */
unsigned SegNum; /* If this is a segment */
- unsigned ImpNum; /* If this is an import */
- struct Memory* Mem; /* If this is a memory area */
+ struct Import* Imp; /* If this is an import */
+ struct MemoryArea* Mem; /* If this is a memory area */
struct Segment* Seg; /* If this is a segment */
struct Section* Sec; /* If section and Obj is NULL */
} V;
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Defines for magic and version */
#define LIB_MAGIC 0x7A55616E
-#define LIB_VERSION 0x000B
+#define LIB_VERSION 0x000C
/* Size of an library file header */
#define LIB_HDR_SIZE 12
/* */
/* */
/* */
-/* (C) 1999-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1999-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "global.h"
#include "fileio.h"
#include "lineinfo.h"
+#include "memarea.h"
#include "segments.h"
#include "spool.h"
-static void BinWriteMem (BinDesc* D, Memory* M)
+static void BinWriteMem (BinDesc* D, MemoryArea* M)
/* Write the segments of one memory area to a file */
{
/* Get the start address of this memory area */
Print (stdout, 1, "Opened `%s'...\n", D->Filename);
/* Dump all memory areas */
- for (I = 0; I < CollCount (&F->MemList); ++I) {
+ for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
/* Get this entry */
- Memory* M = CollAtUnchecked (&F->MemList, I);
+ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I);
Print (stdout, 1, " Dumping `%s'\n", GetString (M->Name));
BinWriteMem (D, M);
}
/* common */
+#include "addrsize.h"
#include "strbuf.h"
/* ld65 */
#include "cfgexpr.h"
#include "error.h"
#include "exports.h"
+#include "expr.h"
#include "scanner.h"
#include "spool.h"
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-/* Type of a CfgExpr */
-enum {
- ceEmpty,
- ceInt,
- ceString
-};
-
-typedef struct CfgExpr CfgExpr;
-struct CfgExpr {
- unsigned Type; /* Type of the expression */
- long IVal; /* Integer value if it's a string */
- StrBuf SVal; /* String value if it's a string */
-};
-
-#define CFGEXPR_INITIALIZER { ceEmpty, 0, STATIC_STRBUF_INITIALIZER }
-
-
-
-/*****************************************************************************/
-/* Forwards */
-/*****************************************************************************/
-
-
-
-static void Expr (CfgExpr* E);
-/* Full expression */
-
-
-
-/*****************************************************************************/
-/* struct CfgExpr */
-/*****************************************************************************/
-
-
-
-static void CE_Done (CfgExpr* E)
-/* Cleanup a CfgExpr struct */
-{
- /* If the type is a string, we must delete the string buffer */
- if (E->Type == ceString) {
- SB_Done (&E->SVal);
- }
-}
-
-
-
-static void CE_AssureInt (const CfgExpr* E)
-/* Make sure, E contains an integer */
-{
- if (E->Type != ceInt) {
- CfgError ("Integer type expected");
- }
-}
-
-
-
/*****************************************************************************/
/* Code */
/*****************************************************************************/
-static void Factor (CfgExpr* E)
-/* Read and return a factor in E */
+static ExprNode* Factor (void)
+/* Read and return a factor */
{
- Export* Sym;
+ ExprNode* N = 0; /* Initialize to avoid compiler warnings */
+ Export* E;
+ unsigned Name;
switch (CfgTok) {
case CFGTOK_IDENT:
- /* An identifier - search an export with the given name */
- Sym = FindExport (GetStrBufId (&CfgSVal));
- if (Sym == 0) {
- CfgError ("Unknown symbol in expression: `%s'",
- SB_GetConstBuf (&CfgSVal));
+ /* Get the name as an id */
+ Name = GetStrBufId (&CfgSVal);
+
+ /* Check if we know the symbol already */
+ E = FindExport (Name);
+ if (E != 0 && IsConstExport (E)) {
+ N = LiteralExpr (GetExportVal (E), 0);
+ } else {
+ N = NewExprNode (0, EXPR_SYMBOL);
+ N->V.Imp = InsertImport (GenImport (Name, ADDR_SIZE_ABS));
}
- /* We can only handle constants */
- if (!IsConstExport (Sym)) {
- CfgError ("Value for symbol `%s' is not constant",
- SB_GetConstBuf (&CfgSVal));
- }
-
- /* Use the symbol value */
- E->IVal = GetExportVal (Sym);
- E->Type = ceInt;
/* Skip the symbol name */
CfgNextTok ();
case CFGTOK_INTCON:
/* An integer constant */
- E->IVal = CfgIVal;
- E->Type = ceInt;
+ N = LiteralExpr (CfgIVal, 0);
CfgNextTok ();
break;
- case CFGTOK_STRCON:
- /* A string constant */
- SB_Copy (&E->SVal, &CfgSVal);
- E->Type = ceString;
- CfgNextTok ();
- break;
-
case CFGTOK_PLUS:
/* Unary plus */
CfgNextTok ();
- Factor (E);
- CE_AssureInt (E);
+ N = Factor ();
break;
case CFGTOK_MINUS:
/* Unary minus */
CfgNextTok ();
- Factor (E);
- CE_AssureInt (E);
- E->IVal = -E->IVal;
+ N = NewExprNode (0, EXPR_UNARY_MINUS);
+ N->Left = Factor ();
break;
case CFGTOK_LPAR:
/* Left parenthesis */
CfgNextTok ();
- Expr (E);
+ N = CfgExpr ();
CfgConsume (CFGTOK_RPAR, "')' expected");
break;
CfgError ("Invalid expression: %d", CfgTok);
break;
}
+
+ /* Return the new expression node */
+ return N;
}
-static void Term (CfgExpr* E)
+static ExprNode* Term (void)
/* Multiplicative operators: * and / */
{
- /* Left operand */
- Factor (E);
+ /* Read left hand side */
+ ExprNode* Root = Factor ();
/* Handle multiplicative operators */
while (CfgTok == CFGTOK_MUL || CfgTok == CFGTOK_DIV) {
- CfgExpr RightSide = CFGEXPR_INITIALIZER;
+ ExprNode* Left;
+ ExprNode* Right;
+ unsigned char Op;
/* Remember the token, then skip it */
cfgtok_t Tok = CfgTok;
CfgNextTok ();
- /* Left side must be an int */
- CE_AssureInt (E);
-
- /* Get the right operand and make sure it's an int */
- Factor (&RightSide);
- CE_AssureInt (&RightSide);
+ /* Move root to left side, then read right side */
+ Left = Root;
+ Right = Factor ();
/* Handle the operation */
switch (Tok) {
-
- case CFGTOK_MUL:
- E->IVal *= RightSide.IVal;
- break;
-
- case CFGTOK_DIV:
- if (RightSide.IVal == 0) {
- CfgError ("Division by zero");
- }
- E->IVal /= RightSide.IVal;
- break;
-
- default:
- Internal ("Unhandled token in Term: %d", Tok);
+ case CFGTOK_MUL: Op = EXPR_MUL; break;
+ case CFGTOK_DIV: Op = EXPR_DIV; break;
+ default: Internal ("Unhandled token in Term: %d", Tok);
}
-
- /* Cleanup RightSide (this is not really needed since it may not
- * contain strings at this point, but call it anyway for clarity.
- */
- CE_Done (&RightSide);
+ Root = NewExprNode (0, Op);
+ Root->Left = Left;
+ Root->Right = Right;
}
+
+ /* Return the expression tree we've created */
+ return Root;
}
-static void SimpleExpr (CfgExpr* E)
+static ExprNode* SimpleExpr (void)
/* Additive operators: + and - */
{
- /* Left operand */
- Term (E);
+ /* Read left hand side */
+ ExprNode* Root = Term ();
/* Handle additive operators */
while (CfgTok == CFGTOK_PLUS || CfgTok == CFGTOK_MINUS) {
- CfgExpr RightSide = CFGEXPR_INITIALIZER;
+ ExprNode* Left;
+ ExprNode* Right;
+ unsigned char Op;
/* Remember the token, then skip it */
cfgtok_t Tok = CfgTok;
CfgNextTok ();
- /* Get the right operand */
- Term (&RightSide);
-
- /* Make sure, left and right side are of the same type */
- if (E->Type != RightSide.Type) {
- CfgError ("Incompatible types in expression");
- }
+ /* Move root to left side, then read right side */
+ Left = Root;
+ Right = Term ();
/* Handle the operation */
switch (Tok) {
-
- case CFGTOK_PLUS:
- /* Plus is defined for strings and ints */
- if (E->Type == ceInt) {
- E->IVal += RightSide.IVal;
- } else if (E->Type == ceString) {
- SB_Append (&E->SVal, &RightSide.SVal);
- } else {
- Internal ("Unhandled type in '+' operator: %u", E->Type);
- }
- break;
-
- case CFGTOK_MINUS:
- /* Operands must be ints */
- CE_AssureInt (E);
- E->IVal -= RightSide.IVal;
- break;
-
- default:
- Internal ("Unhandled token in SimpleExpr: %d", Tok);
+ case CFGTOK_PLUS: Op = EXPR_PLUS; break;
+ case CFGTOK_MINUS: Op = EXPR_MINUS; break;
+ default: Internal ("Unhandled token in SimpleExpr: %d", Tok);
}
-
- /* Cleanup RightSide */
- CE_Done (&RightSide);
+ Root = NewExprNode (0, Op);
+ Root->Left = Left;
+ Root->Right = Right;
}
+
+ /* Return the expression tree we've created */
+ return Root;
}
-static void Expr (CfgExpr* E)
+ExprNode* CfgExpr (void)
/* Full expression */
{
- SimpleExpr (E);
+ return SimpleExpr ();
}
-long CfgIntExpr (void)
-/* Read an expression, make sure it's an int, and return its value */
+long CfgConstExpr (void)
+/* Read an integer expression, make sure its constant and return its value */
{
long Val;
- CfgExpr E = CFGEXPR_INITIALIZER;
-
/* Parse the expression */
- Expr (&E);
+ ExprNode* Expr = CfgExpr ();
- /* Make sure it's an integer */
- CE_AssureInt (&E);
+ /* Check that it's const */
+ if (!IsConstExpr (Expr)) {
+ CfgError ("Constant expression expected");
+ }
/* Get the value */
- Val = E.IVal;
+ Val = GetExprVal (Expr);
- /* Cleaup E */
- CE_Done (&E);
+ /* Cleanup E */
+ FreeExpr (Expr);
/* Return the value */
return Val;
-long CfgCheckedIntExpr (long Min, long Max)
+long CfgCheckedConstExpr (long Min, long Max)
/* Read an expression, make sure it's an int and in range, then return its
* value.
*/
{
/* Get the value */
- long Val = CfgIntExpr ();
+ long Val = CfgConstExpr ();
/* Check the range */
if (Val < Min || Val > Max) {
- CfgError ("Range error");
+ CfgError ("Range error");
}
/* Return the value */
/* */
/* */
/* */
-/* (C) 2005, Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* (C) 2005-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+/* common */
+#include "exprdefs.h"
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
-long CfgIntExpr (void);
-/* Read an expression, make sure it's an int, and return its value */
+ExprNode* CfgExpr (void);
+/* Read an integer expression and return its value */
+
+long CfgConstExpr (void);
+/* Read an integer expression, make sure its constant and return its value */
-long CfgCheckedIntExpr (long Min, long Max);
+long CfgCheckedConstExpr (long Min, long Max);
/* Read an expression, make sure it's an int and in range, then return its
* value.
*/
#include "config.h"
#include "error.h"
#include "exports.h"
+#include "expr.h"
#include "global.h"
+#include "memarea.h"
#include "o65.h"
#include "objdata.h"
#include "scanner.h"
static Collection FileList = STATIC_COLLECTION_INITIALIZER;
/* Memory list */
-static Collection MemoryList = STATIC_COLLECTION_INITIALIZER;
+static Collection MemoryAreas = STATIC_COLLECTION_INITIALIZER;
/* Memory attributes */
#define MA_START 0x0001
#define MA_FILL 0x0020
#define MA_FILLVAL 0x0040
-
-
/* Segment list */
static Collection SegDescList = STATIC_COLLECTION_INITIALIZER;
#define SA_START 0x0080
#define SA_OPTIONAL 0x0100
-
+/* Symbol structure. It is used for o65 imports and exports, but also for
+ * symbols from the SYMBOLS sections (symbols defined in the config file or
+ * forced imports).
+ */
+typedef struct Symbol Symbol;
+struct Symbol {
+ const char* CfgName; /* Config file name */
+ unsigned CfgLine; /* Config file position */
+ unsigned CfgCol;
+ unsigned Name; /* Symbol name */
+ unsigned Flags; /* Symbol flags */
+ long Val; /* Symbol value if any */
+};
+
+/* Collections with symbols */
+static Collection O65Imports = STATIC_COLLECTION_INITIALIZER;
+static Collection O65Exports = STATIC_COLLECTION_INITIALIZER;
+static Collection Symbols = STATIC_COLLECTION_INITIALIZER;
+
+/* Symbol flags */
+#define SYM_NONE 0x00 /* No special meaning */
+#define SYM_DEF 0x01 /* Symbol defined in the config file */
+#define SYM_WEAK 0x02 /* Defined symbol is weak */
+#define SYM_IMPORT 0x04 /* A forced import */
/* Descriptor holding information about the binary formats */
static BinDesc* BinFmtDesc = 0;
-static void FileInsert (File* F, Memory* M)
+static void FileInsert (File* F, MemoryArea* M)
/* Insert the memory area into the files list */
{
M->F = F;
- CollAppend (&F->MemList, M);
+ CollAppend (&F->MemoryAreas, M);
}
-static Memory* CfgFindMemory (unsigned Name)
+static MemoryArea* CfgFindMemory (unsigned Name)
/* Find the memory are with the given name. Return NULL if not found */
{
unsigned I;
- for (I = 0; I < CollCount (&MemoryList); ++I) {
- Memory* M = CollAtUnchecked (&MemoryList, I);
+ for (I = 0; I < CollCount (&MemoryAreas); ++I) {
+ MemoryArea* M = CollAtUnchecked (&MemoryAreas, I);
if (M->Name == Name) {
return M;
}
-static Memory* CfgGetMemory (unsigned Name)
+static MemoryArea* CfgGetMemory (unsigned Name)
/* Find the memory are with the given name. Print an error on an invalid name */
{
- Memory* M = CfgFindMemory (Name);
+ MemoryArea* M = CfgFindMemory (Name);
if (M == 0) {
CfgError ("Invalid memory area `%s'", GetString (Name));
}
-static void SegDescInsert (SegDesc* S)
-/* Insert a segment descriptor into the list of segment descriptors */
-{
- /* Insert the struct into the list */
- CollAppend (&SegDescList, S);
-}
-
-
-
-static void MemoryInsert (Memory* M, SegDesc* S)
+static void MemoryInsert (MemoryArea* M, SegDesc* S)
/* Insert the segment descriptor into the memory area list */
{
/* Insert the segment into the segment list of the memory area */
+static Symbol* NewSymbol (unsigned Name, unsigned Flags, long Val)
+/* Create a new Symbol structure with the given name name and flags. The
+ * current config file position is recorded in the returned struct.
+ */
+{
+ /* Allocate memory */
+ Symbol* Sym = xmalloc (sizeof (Symbol));
+
+ /* Initialize the fields */
+ Sym->CfgName = CfgGetName ();
+ Sym->CfgLine = CfgErrorLine;
+ Sym->CfgCol = CfgErrorCol;
+ Sym->Name = Name;
+ Sym->Flags = Flags;
+ Sym->Val = Val;
+
+ /* Return the initialized struct */
+ return Sym;
+}
+
+
+
+static Symbol* NewO65Symbol (void)
+/* Create a new Symbol structure with the name in the current CfgSVal variable
+ * ready for use as an o65 symbol. The current config file position is recorded
+ * in the returned struct.
+ */
+{
+ return NewSymbol (GetStrBufId (&CfgSVal), SYM_NONE, 0);
+}
+
+
+
static File* NewFile (unsigned Name)
/* Create a new file descriptor and insert it into the list */
{
F->Name = Name;
F->Flags = 0;
F->Format = BINFMT_DEFAULT;
- InitCollection (&F->MemList);
+ InitCollection (&F->MemoryAreas);
/* Insert the struct into the list */
CollAppend (&FileList, F);
-static Memory* NewMemory (unsigned Name)
-/* Create a new memory section and insert it into the list */
+static MemoryArea* CreateMemoryArea (unsigned Name)
+/* Create a new memory area and insert it into the list */
{
/* Check for duplicate names */
- Memory* M = CfgFindMemory (Name);
+ MemoryArea* M = CfgFindMemory (Name);
if (M) {
CfgError ("Memory area `%s' defined twice", GetString (Name));
}
- /* Allocate memory */
- M = xmalloc (sizeof (Memory));
-
- /* Initialize the fields */
- M->Name = Name;
- M->Attr = 0;
- M->Flags = 0;
- M->Start = 0;
- M->Size = 0;
- M->FillLevel = 0;
- M->FillVal = 0;
- M->Relocatable = 0;
- InitCollection (&M->SegList);
- M->F = 0;
+ /* Create a new memory area */
+ M = NewMemoryArea (Name);
- /* Insert the struct into the list */
- CollAppend (&MemoryList, M);
+ /* Insert the struct into the list ... */
+ CollAppend (&MemoryAreas, M);
/* ...and return it */
return M;
static SegDesc* NewSegDesc (unsigned Name)
-/* Create a segment descriptor */
+/* Create a segment descriptor and insert it into the list */
{
- Segment* Seg;
/* Check for duplicate names */
SegDesc* S = CfgFindSegDesc (Name);
CfgError ("Segment `%s' defined twice", GetString (Name));
}
- /* Search for the actual segment in the input files. The function may
- * return NULL (no such segment), this is checked later.
- */
- Seg = SegFind (Name);
-
/* Allocate memory */
S = xmalloc (sizeof (SegDesc));
/* Initialize the fields */
S->Name = Name;
- S->Seg = Seg;
+ S->Seg = 0;
S->Attr = 0;
S->Flags = 0;
S->Align = 0;
+ /* Insert the struct into the list ... */
+ CollAppend (&SegDescList, S);
+
/* ...and return it */
return S;
}
/*****************************************************************************/
-/* Code */
+/* Config file parsing */
/*****************************************************************************/
while (CfgTok == CFGTOK_IDENT) {
/* Create a new entry on the heap */
- Memory* M = NewMemory (GetStrBufId (&CfgSVal));
+ MemoryArea* M = CreateMemoryArea (GetStrBufId (&CfgSVal));
/* Skip the name and the following colon */
CfgNextTok ();
case CFGTOK_START:
FlagAttr (&M->Attr, MA_START, "START");
- M->Start = CfgIntExpr ();
+ M->StartExpr = CfgExpr ();
break;
case CFGTOK_SIZE:
FlagAttr (&M->Attr, MA_SIZE, "SIZE");
- M->Size = CfgIntExpr ();
- break;
+ M->SizeExpr = CfgExpr ();
+ break;
case CFGTOK_TYPE:
FlagAttr (&M->Attr, MA_TYPE, "TYPE");
case CFGTOK_FILLVAL:
FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL");
- M->FillVal = (unsigned char) CfgCheckedIntExpr (0, 0xFF);
+ M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF);
break;
default:
case CFGTOK_ALIGN:
FlagAttr (&S->Attr, SA_ALIGN, "ALIGN");
- Val = CfgCheckedIntExpr (1, 0x10000);
+ Val = CfgCheckedConstExpr (1, 0x10000);
S->Align = BitFind (Val);
if ((0x01L << S->Align) != Val) {
CfgError ("Alignment must be a power of 2");
case CFGTOK_ALIGN_LOAD:
FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD");
- Val = CfgCheckedIntExpr (1, 0x10000);
+ Val = CfgCheckedConstExpr (1, 0x10000);
S->AlignLoad = BitFind (Val);
if ((0x01L << S->AlignLoad) != Val) {
CfgError ("Alignment must be a power of 2");
case CFGTOK_OFFSET:
FlagAttr (&S->Attr, SA_OFFSET, "OFFSET");
- S->Addr = CfgCheckedIntExpr (1, 0x1000000);
+ S->Addr = CfgCheckedConstExpr (1, 0x1000000);
S->Flags |= SF_OFFSET;
break;
case CFGTOK_START:
FlagAttr (&S->Attr, SA_START, "START");
- S->Addr = CfgCheckedIntExpr (1, 0x1000000);
+ S->Addr = CfgCheckedConstExpr (1, 0x1000000);
S->Flags |= SF_START;
break;
S->Run = S->Load;
}
- /* If the segment is marked as BSS style, and if the segment exists
- * in any of the object file, check that there's no initialized data
- * in the segment.
- */
- if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
- Warning ("%s(%u): Segment with type `bss' contains initialized data",
- CfgGetName (), CfgErrorLine);
- }
-
/* An attribute of ALIGN_LOAD doesn't make sense if there are no
* separate run and load memory areas.
*/
CfgError ("Only one of ALIGN, START, OFFSET may be used");
}
- /* If this segment does exist in any of the object files, insert the
- * descriptor into the list of segment descriptors. Otherwise print a
- * warning and discard it, because the segment pointer in the
- * descriptor is invalid.
- */
- if (S->Seg != 0) {
- /* Insert the descriptor into the list of all descriptors */
- SegDescInsert (S);
- /* Insert the segment into the memory area list */
- MemoryInsert (S->Run, S);
- if (S->Load != S->Run) {
- /* We have separate RUN and LOAD areas */
- MemoryInsert (S->Load, S);
- }
- } else {
- /* Print a warning if the segment is not optional */
- if ((S->Flags & SF_OPTIONAL) == 0) {
- CfgWarning ("Segment `%s' does not exist", GetString (S->Name));
- }
- /* Discard the descriptor */
- FreeSegDesc (S);
- }
-
/* Skip the semicolon */
CfgConsumeSemi ();
}
unsigned AttrFlags = atNone;
/* Remember the attributes read */
- unsigned CfgSValId;
unsigned OS = 0; /* Initialize to keep gcc happy */
unsigned Version = 0;
AttrFlags |= atExport;
/* We expect an identifier */
CfgAssureIdent ();
- /* Convert the string into a string index */
- CfgSValId = GetStrBufId (&CfgSVal);
- /* Check if the export symbol is also defined as an import. */
- if (O65GetImport (O65FmtDesc, CfgSValId) != 0) {
- CfgError ("Exported symbol `%s' cannot be an import",
- SB_GetConstBuf (&CfgSVal));
- }
- /* Check if we have this symbol defined already. The entry
- * routine will check this also, but we get a more verbose
- * error message when checking it here.
- */
- if (O65GetExport (O65FmtDesc, CfgSValId) != 0) {
- CfgError ("Duplicate exported symbol: `%s'",
- SB_GetConstBuf (&CfgSVal));
- }
- /* Insert the symbol into the table */
- O65SetExport (O65FmtDesc, CfgSValId);
+ /* Remember it as an export for later */
+ CollAppend (&O65Exports, NewO65Symbol ());
/* Eat the identifier token */
CfgNextTok ();
break;
AttrFlags |= atImport;
/* We expect an identifier */
CfgAssureIdent ();
- /* Convert the string into a string index */
- CfgSValId = GetStrBufId (&CfgSVal);
- /* Check if the imported symbol is also defined as an export. */
- if (O65GetExport (O65FmtDesc, CfgSValId) != 0) {
- CfgError ("Imported symbol `%s' cannot be an export",
- SB_GetConstBuf (&CfgSVal));
- }
- /* Check if we have this symbol defined already. The entry
- * routine will check this also, but we get a more verbose
- * error message when checking it here.
- */
- if (O65GetImport (O65FmtDesc, CfgSValId) != 0) {
- CfgError ("Duplicate imported symbol: `%s'",
- SB_GetConstBuf (&CfgSVal));
- }
- /* Insert the symbol into the table */
- O65SetImport (O65FmtDesc, CfgSValId);
+ /* Remember it as an import for later */
+ CollAppend (&O65Imports, NewO65Symbol ());
/* Eat the identifier token */
CfgNextTok ();
break;
case CFGTOK_TYPE:
/* Cannot have this attribute twice */
FlagAttr (&AttrFlags, atType, "TYPE");
- /* Get the type of the executable */
+ /* Get the type of the executable */
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
switch (CfgTok) {
/* Cannot have this attribute twice */
FlagAttr (&AttrFlags, atID, "ID");
/* We're expecting a number in the 0..$FFFF range*/
- ModuleId = (unsigned) CfgCheckedIntExpr (0, 0xFFFF);
+ ModuleId = (unsigned) CfgCheckedConstExpr (0, 0xFFFF);
break;
case CFGTOK_VERSION:
/* Cannot have this attribute twice */
FlagAttr (&AttrFlags, atVersion, "VERSION");
/* We're expecting a number in byte range */
- Version = (unsigned) CfgCheckedIntExpr (0, 0xFF);
+ Version = (unsigned) CfgCheckedConstExpr (0, 0xFF);
break;
default:
/* Don't allow this twice */
FlagAttr (&AttrFlags, atDefault, "DEFAULT");
/* We expect a numeric expression */
- DefStartAddr = CfgCheckedIntExpr (0, 0xFFFFFF);
+ DefStartAddr = CfgCheckedConstExpr (0, 0xFFFFFF);
break;
default:
while (CfgTok == CFGTOK_IDENT) {
long Val = 0L;
- int Weak = 0;
- Export* E;
+ unsigned Flags = SYM_NONE;
/* Remember the name */
unsigned Name = GetStrBufId (&CfgSVal);
/* Make sure the next token is an integer expression, read and
* skip it.
*/
- Val = CfgIntExpr ();
+ Val = CfgConstExpr ();
+
+ /* This is a defined symbol */
+ Flags = SYM_DEF;
} else {
/* Bitmask to remember the attributes we got already */
enum {
- atNone = 0x0000,
+ atNone = 0x0000,
atValue = 0x0001,
atWeak = 0x0002
};
/* Don't allow this twice */
FlagAttr (&AttrFlags, atValue, "VALUE");
/* We expect a numeric expression */
- Val = CfgIntExpr ();
+ Val = CfgConstExpr ();
+ /* Symbol is defined */
+ Flags |= SYM_DEF;
break;
case CFGTOK_WEAK:
/* Don't allow this twice */
FlagAttr (&AttrFlags, atWeak, "WEAK");
CfgBoolToken ();
- Weak = (CfgTok == CFGTOK_TRUE);
+ if (CfgTok == CFGTOK_TRUE) {
+ Flags |= SYM_WEAK;
+ }
CfgNextTok ();
break;
/* Check if we have all mandatory attributes */
AttrCheck (AttrFlags, atValue, "VALUE");
-
- /* Weak is optional, the default are non weak symbols */
- if ((AttrFlags & atWeak) == 0) {
- Weak = 0;
- }
-
}
- /* Check if the symbol is already defined */
- if ((E = FindExport (Name)) != 0 && !IsUnresolvedExport (E)) {
- /* If the symbol is not marked as weak, this is an error.
- * Otherwise ignore the symbol from the config.
- */
- if (!Weak) {
- CfgError ("Symbol `%s' is already defined", GetString (Name));
- }
- } else {
- /* The symbol is undefined, generate an export */
- CreateConstExport (Name, Val);
- }
+ /* Remember the symbol for later */
+ CollAppend (&Symbols, NewSymbol (Name, Flags, Val));
/* Skip the semicolon */
CfgConsumeSemi ();
+/*****************************************************************************/
+/* Config file processing */
+/*****************************************************************************/
+
+
+
+static void ProcessMemory (void)
+/* Process the MEMORY section */
+{
+ /* Walk over the list with the memory areas */
+ unsigned I;
+ for (I = 0; I < CollCount (&MemoryAreas); ++I) {
+
+ /* Get the next memory area */
+ MemoryArea* M = CollAtUnchecked (&MemoryAreas, I);
+
+ /* Remember if this is a relocatable memory area */
+ M->Relocatable = RelocatableBinFmt (M->F->Format);
+
+ /* Resolve the expressions */
+ if (!IsConstExpr (M->StartExpr)) {
+ Error ("Start address of memory area `%s' is not constant",
+ GetString (M->Name));
+ }
+ M->Start = GetExprVal (M->StartExpr);
+
+ if (!IsConstExpr (M->SizeExpr)) {
+ Error ("Size of memory area `%s' is not constant",
+ GetString (M->Name));
+ }
+ M->Size = GetExprVal (M->SizeExpr);
+
+ /* Mark the memory area as placed */
+ M->Flags |= MF_PLACED;
+ }
+}
+
+
+
+static void ProcessSegments (void)
+/* Process the SEGMENTS section */
+{
+ unsigned I;
+
+ /* Walk over the list of segment descriptors */
+ I = 0;
+ while (I < CollCount (&SegDescList)) {
+
+ /* Get the next segment descriptor */
+ SegDesc* S = CollAtUnchecked (&SegDescList, I);
+
+ /* Search for the actual segment in the input files. The function may
+ * return NULL (no such segment), this is checked later.
+ */
+ S->Seg = SegFind (S->Name);
+
+ /* If the segment is marked as BSS style, and if the segment exists
+ * in any of the object file, check that there's no initialized data
+ * in the segment.
+ */
+ if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
+ Warning ("Segment `%s' with type `bss' contains initialized data",
+ GetString (S->Name));
+ }
+
+ /* If this segment does exist in any of the object files, insert the
+ * segment into the load/run memory areas. Otherwise print a warning
+ * and discard it, because the segment pointer in the descriptor is
+ * invalid.
+ */
+ if (S->Seg != 0) {
+
+ /* Insert the segment into the memory area list */
+ MemoryInsert (S->Run, S);
+ if (S->Load != S->Run) {
+ /* We have separate RUN and LOAD areas */
+ MemoryInsert (S->Load, S);
+ }
+
+ /* Process the next segment descriptor in the next run */
+ ++I;
+
+ } else {
+
+ /* Print a warning if the segment is not optional */
+ if ((S->Flags & SF_OPTIONAL) == 0) {
+ CfgWarning ("Segment `%s' does not exist", GetString (S->Name));
+ }
+
+ /* Discard the descriptor and remove it from the collection */
+ FreeSegDesc (S);
+ CollDelete (&SegDescList, I);
+ }
+ }
+}
+
+
+
+static void ProcessO65 (void)
+/* Process the o65 format section */
+{
+ unsigned I;
+
+ /* Walk over the imports, check and add them to the o65 data */
+ for (I = 0; I < CollCount (&O65Imports); ++I) {
+
+ /* Get the import */
+ Symbol* Sym = CollAtUnchecked (&O65Imports, I);
+
+ /* Check if we have this symbol defined already. The entry
+ * routine will check this also, but we get a more verbose
+ * error message when checking it here.
+ */
+ if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
+ Error ("%s(%u): Duplicate imported o65 symbol: `%s'",
+ Sym->CfgName, Sym->CfgLine, GetString (Sym->Name));
+ }
+
+ /* Insert the symbol into the table */
+ O65SetImport (O65FmtDesc, Sym->Name);
+ }
+
+ /* Walk over the exports, check and add them to the o65 data */
+ for (I = 0; I < CollCount (&O65Exports); ++I) {
+
+ /* Get the export */
+ Symbol* Sym = CollAtUnchecked (&O65Exports, I);
+
+ /* Check if the export symbol is also defined as an import. */
+ if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
+ Error ("%s(%u): Exported o65 symbol `%s' cannot also be an o65 import",
+ Sym->CfgName, Sym->CfgLine, GetString (Sym->Name));
+ }
+
+ /* Check if we have this symbol defined already. The entry
+ * routine will check this also, but we get a more verbose
+ * error message when checking it here.
+ */
+ if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
+ Error ("%s(%u): Duplicate exported o65 symbol: `%s'",
+ Sym->CfgName, Sym->CfgLine, GetString (Sym->Name));
+ }
+
+ /* Insert the symbol into the table */
+ O65SetExport (O65FmtDesc, Sym->Name);
+ }
+}
+
+
+
+static void ProcessBin (void)
+/* Process the bin format section */
+{
+}
+
+
+
+static void ProcessFormats (void)
+/* Process the target format section */
+{
+ ProcessO65 ();
+ ProcessBin ();
+}
+
+
+
+static void ProcessSymbols (void)
+/* Process the SYMBOLS section */
+{
+ Export* E;
+
+ /* Walk over all symbols */
+ unsigned I;
+ for (I = 0; I < CollCount (&Symbols); ++I) {
+
+ /* Get the next symbol */
+ Symbol* Sym = CollAtUnchecked (&Symbols, I);
+
+ /* Do we define this symbol? */
+ if ((Sym->Flags & SYM_DEF) != 0) {
+ /* Check if the symbol is already defined somewhere else */
+ if ((E = FindExport (Sym->Name)) != 0 && !IsUnresolvedExport (E)) {
+ /* If the symbol is not marked as weak, this is an error.
+ * Otherwise ignore the symbol from the config.
+ */
+ if ((Sym->Flags & SYM_WEAK) == 0) {
+ CfgError ("Symbol `%s' is already defined",
+ GetString (Sym->Name));
+ }
+ } else {
+ /* The symbol is undefined, generate an export */
+ CreateConstExport (Sym->Name, Sym->Val);
+ }
+
+ } else {
+
+
+ }
+ }
+}
+
+
+
+void CfgProcess (void)
+/* Process the config file after reading in object files and libraries */
+{
+ ProcessSymbols (); /* ######## */
+ ProcessMemory ();
+ ProcessSegments ();
+ ProcessFormats ();
+}
+
+
+
static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
/* Create the defines for a RUN segment */
{
* segments while doing this.
*/
unsigned I;
- for (I = 0; I < CollCount (&MemoryList); ++I) {
+ for (I = 0; I < CollCount (&MemoryAreas); ++I) {
unsigned J;
/* Get this entry */
- Memory* M = CollAtUnchecked (&MemoryList, I);
+ MemoryArea* M = CollAtUnchecked (&MemoryAreas, I);
/* Get the start address of this memory area */
unsigned long Addr = M->Start;
- /* Remember if this is a relocatable memory area */
- M->Relocatable = RelocatableBinFmt (M->F->Format);
-
/* Walk through the segments in this memory area */
for (J = 0; J < CollCount (&M->SegList); ++J) {
S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
S->Seg->Relocatable = M->Relocatable;
+ /* Remember that this segment is placed */
+ S->Seg->Placed = 1;
+
} else if (S->Load == M) {
/* This is the load memory area, *and* run and load are
File* F = CollAtUnchecked (&FileList, I);
/* We don't need to look at files with no memory areas */
- if (CollCount (&F->MemList) > 0) {
+ if (CollCount (&F->MemoryAreas) > 0) {
/* Is there an output file? */
if (SB_GetLen (GetStrBuf (F->Name)) > 0) {
break;
case BINFMT_O65:
- O65WriteTarget (O65FmtDesc, F);
+ O65WriteTarget (O65FmtDesc, F);
break;
default:
* loading into these memory areas in this file as dumped.
*/
unsigned J;
- for (J = 0; J < CollCount (&F->MemList); ++J) {
+ for (J = 0; J < CollCount (&F->MemoryAreas); ++J) {
unsigned K;
/* Get this entry */
- Memory* M = CollAtUnchecked (&F->MemList, J);
+ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, J);
/* Debugging */
Print (stdout, 2, "Skipping `%s'...\n", GetString (M->Name));
+/* Forward for struct MemoryArea */
+struct MemoryArea;
+
/* File list entry */
typedef struct File File;
struct File {
unsigned Name; /* Name index of the file */
- unsigned Flags;
- unsigned Format; /* Output format */
- Collection MemList; /* List of memory areas in this file */
-};
-
-/* Memory list entry */
-typedef struct Memory Memory;
-struct Memory {
- unsigned Name; /* Name index of the memory section */
- unsigned Attr; /* Which values are valid? */
- unsigned Flags; /* Set of bitmapped flags */
- unsigned long Start; /* Start address */
- unsigned long Size; /* Length of memory section */
- unsigned long FillLevel; /* Actual fill level of segment */
- unsigned char FillVal; /* Value used to fill rest of seg */
- unsigned char Relocatable; /* Memory area is relocatable */
- Collection SegList; /* List of segments for this section */
- File* F; /* File that contains the entry */
+ unsigned Flags;
+ unsigned Format; /* Output format */
+ Collection MemoryAreas; /* List of memory areas in this file */
};
/* Segment descriptor entry */
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 */
+ struct MemoryArea* Load; /* Load memory section */
+ struct MemoryArea* Run; /* Run memory section */
unsigned long Addr; /* Start address or offset into segment */
unsigned char Align; /* Run area alignment if given */
unsigned char AlignLoad; /* Load area alignment if given */
};
-/* Memory flags */
-#define MF_DEFINE 0x0001 /* Define start and size */
-#define MF_FILL 0x0002 /* Fill segment */
-#define MF_RO 0x0004 /* Read only memory area */
-#define MF_OVERFLOW 0x0008 /* Memory area overflow */
-
/* Segment flags */
#define SF_RO 0x0001 /* Read only segment */
#define SF_BSS 0x0002 /* Segment is BSS style segment */
void CfgRead (void);
/* Read the configuration */
+void CfgProcess (void);
+/* Process the config file after reading in object files and libraries */
+
unsigned CfgAssignSegments (void);
/* Assign segments, define linker symbols where requested. The function will
* return the number of memory area overflows (so zero means anything went ok).
#include "expr.h"
#include "fileio.h"
#include "global.h"
+#include "memarea.h"
#include "objdata.h"
#include "spool.h"
-Import* GenImport (const char* Name, unsigned char AddrSize)
+Import* GenImport (unsigned Name, unsigned char AddrSize)
/* Generate a new import with the given name and address size and return it */
{
/* Create a new import */
Import* I = NewImport (AddrSize, 0);
/* Read the name */
- I->Name = GetStringId (Name);
+ I->Name = Name;
/* Check the address size */
if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) {
-void InsertImport (Import* I)
-/* Insert an import into the table */
+Import* InsertImport (Import* I)
+/* Insert an import into the table, return I */
{
Export* E;
/* Mark the import so we know it's in the list */
I->Flags |= IMP_INLIST;
+
+ /* Return the import to allow shorter code */
+ return I;
}
-Export* CreateMemoryExport (unsigned Name, Memory* Mem, unsigned long Offs)
+Export* CreateMemoryExport (unsigned Name, MemoryArea* Mem, unsigned long Offs)
/* Create an relative export for a memory area offset */
{
/* Create a new export */
/* */
/* */
/* */
-/* (C) 1998-2009, Ullrich von Bassewitz */
+/* (C) 1998-2010, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "filepos.h"
/* ld65 */
-#include "objdata.h"
#include "config.h"
+#include "memarea.h"
+#include "objdata.h"
Import* ReadImport (FILE* F, ObjData* Obj);
/* Read an import from a file and insert it into the table */
-Import* GenImport (const char* Name, unsigned char AddrSize);
+Import* GenImport (unsigned Name, unsigned char AddrSize);
/* Generate a new import with the given name and address size and return it */
-void InsertImport (Import* I);
-/* Insert an import into the table */
+Import* InsertImport (Import* I);
+/* Insert an import into the table, return I */
void FreeExport (Export* E);
/* Free an export. NOTE: This won't remove the export from the exports table,
Export* CreateConstExport (unsigned Name, long Value);
/* Create an export for a literal date */
-Export* CreateMemoryExport (unsigned Name, Memory* Mem, unsigned long Offs);
+Export* CreateMemoryExport (unsigned Name, MemoryArea* Mem, unsigned long Offs);
/* Create an relative export for a memory area offset */
Export* CreateSegmentExport (unsigned Name, Segment* Seg, unsigned long Offs);
#include "global.h"
#include "error.h"
#include "fileio.h"
+#include "memarea.h"
#include "segments.h"
#include "expr.h"
/*****************************************************************************/
-/* Helpers */
+/* Code */
/*****************************************************************************/
-static ExprNode* NewExprNode (ObjData* O)
+ExprNode* NewExprNode (ObjData* O, unsigned char Op)
/* Create a new expression node */
{
/* Allocate fresh memory */
ExprNode* N = xmalloc (sizeof (ExprNode));
- N->Op = EXPR_NULL;
+ N->Op = Op;
N->Left = 0;
N->Right = 0;
N->Obj = O;
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
void FreeExpr (ExprNode* Root)
/* Free the expression, Root is pointing to. */
{
case EXPR_SECTION:
/* A section expression is const if the segment it is in is
- * not relocatable.
+ * not relocatable and already placed.
*/
S = GetExprSection (Root);
- return !S->Seg->Relocatable;
+ return !S->Seg->Relocatable && S->Seg->Placed;
case EXPR_SEGMENT:
- /* A segment is const if it is not relocatable */
- return !Root->V.Seg->Relocatable;
+ /* A segment is const if it is not relocatable and placed */
+ return !Root->V.Seg->Relocatable && Root->V.Seg->Placed;
case EXPR_MEMAREA:
- /* A memory area is const if it is not relocatable */
- return !Root->V.Mem->Relocatable;
+ /* A memory area is const if it is not relocatable and placed */
+ return !Root->V.Mem->Relocatable &&
+ (Root->V.Mem->Flags & MF_PLACED);
default:
/* Anything else is not const */
PRECONDITION (Expr->Op == EXPR_SYMBOL);
/* Return the import */
- return CollAt (&Expr->Obj->Imports, Expr->V.ImpNum);
+ return Expr->V.Imp;
}
ExprNode* LiteralExpr (long Val, ObjData* O)
/* Return an expression tree that encodes the given literal value */
{
- ExprNode* Expr = NewExprNode (O);
- Expr->Op = EXPR_LITERAL;
+ ExprNode* Expr = NewExprNode (O, EXPR_LITERAL);
Expr->V.IVal = Val;
return Expr;
}
-ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O)
+ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O)
/* Return an expression tree that encodes an offset into a memory area */
{
ExprNode* Root;
- ExprNode* Expr = NewExprNode (O);
- Expr->Op = EXPR_MEMAREA;
+ ExprNode* Expr = NewExprNode (O, EXPR_MEMAREA);
Expr->V.Mem = Mem;
if (Offs != 0) {
- Root = NewExprNode (O);
- Root->Op = EXPR_PLUS;
+ Root = NewExprNode (O, EXPR_PLUS);
Root->Left = Expr;
Root->Right = LiteralExpr (Offs, O);
} else {
{
ExprNode* Root;
- ExprNode* Expr = NewExprNode (O);
- Expr->Op = EXPR_SEGMENT;
+ ExprNode* Expr = NewExprNode (O, EXPR_SEGMENT);
Expr->V.Seg = Seg;
if (Offs != 0) {
- Root = NewExprNode (O);
- Root->Op = EXPR_PLUS;
+ Root = NewExprNode (O, EXPR_PLUS);
Root->Left = Expr;
Root->Right = LiteralExpr (Offs, O);
} else {
{
ExprNode* Root;
- ExprNode* Expr = NewExprNode (O);
- Expr->Op = EXPR_SECTION;
+ ExprNode* Expr = NewExprNode (O, EXPR_SECTION);
Expr->V.Sec = Sec;
if (Offs != 0) {
- Root = NewExprNode (O);
- Root->Op = EXPR_PLUS;
+ Root = NewExprNode (O, EXPR_PLUS);
Root->Left = Expr;
Root->Right = LiteralExpr (Offs, O);
} else {
/* Read an expression from the given file */
{
ExprNode* Expr;
+ unsigned ImpNum;
/* Read the node tag and handle NULL nodes */
unsigned char Op = Read8 (F);
}
/* Create a new node */
- Expr = NewExprNode (O);
- Expr->Op = Op;
+ Expr = NewExprNode (O, Op);
/* Check the tag and handle the different expression types */
if (EXPR_IS_LEAF (Op)) {
switch (Op) {
case EXPR_LITERAL:
- Expr->V.IVal = Read32Signed (F);
- break;
+ Expr->V.IVal = Read32Signed (F);
+ break;
case EXPR_SYMBOL:
- /* Read the import number */
- Expr->V.ImpNum = ReadVar (F);
- break;
+ /* Read the import number */
+ ImpNum = ReadVar (F);
+ Expr->V.Imp = CollAt (&O->Imports, ImpNum);
+ break;
case EXPR_SECTION:
- /* Read the segment number */
- Expr->V.SegNum = Read8 (F);
- break;
+ /* Read the segment number */
+ Expr->V.SegNum = Read8 (F);
+ break;
default:
- Error ("Invalid expression op: %02X", Op);
+ Error ("Invalid expression op: %02X", Op);
}
return (E1->V.IVal == E2->V.IVal);
case EXPR_SYMBOL:
- /* Import number must be identical */
- return (E1->V.ImpNum == E2->V.ImpNum);
+ /* Import must be identical */
+ return (E1->V.Imp == E2->V.Imp);
case EXPR_SECTION:
/* Section must be identical */
case EXPR_MEMAREA:
/* Memory area must be identical */
- return (E1->V.Mem == E2->V.Mem );
+ return (E1->V.Mem == E2->V.Mem);
default:
/* Not a leaf node */
+ExprNode* NewExprNode (ObjData* O, unsigned char Op);
+/* Create a new expression node */
+
void FreeExpr (ExprNode* Root);
/* Free the expression tree, Root is pointing to. */
ExprNode* LiteralExpr (long Val, ObjData* O);
/* Return an expression tree that encodes the given literal value */
-ExprNode* MemoryExpr (Memory* Mem, long Offs, ObjData* O);
+ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O);
/* Return an expression tree that encodes an offset into the memory area */
ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O);
/* Read the string pool */
ObjReadStrPool (L->F, FileGetPos (L->F), O);
- /* Skip the export size, then read the exports */
- (void) ReadVar (L->F);
- ObjReadExports (L->F, FileGetPos (L->F), O);
-
/* Skip the import size, then read the imports */
(void) ReadVar (L->F);
ObjReadImports (L->F, FileGetPos (L->F), O);
+ /* Skip the export size, then read the exports */
+ (void) ReadVar (L->F);
+ ObjReadExports (L->F, FileGetPos (L->F), O);
+
/* Done */
return O;
}
} else {
CfgSetName (PathName);
}
+
+ /* Read the config */
+ CfgRead ();
}
/* Use default address size (which for now is always absolute
* addressing)
*/
- InsertImport (GenImport (Arg, ADDR_SIZE_ABS));
+ InsertImport (GenImport (GetStringId (Arg), ADDR_SIZE_ABS));
} else {
A[ColPos - Arg] = '\0';
/* Generate the import */
- InsertImport (GenImport (A, AddrSize));
+ InsertImport (GenImport (GetStringId (A), AddrSize));
/* Delete the copy of the argument */
xfree (A);
/* Set the target data */
DefaultBinFmt = D->BinFmt;
CfgSetBuf (D->Cfg);
+
+ /* Read the target config */
+ CfgRead ();
}
/* Check if we have open library groups */
LibCheckGroup ();
- /* Read the config file */
- CfgRead ();
-
/* Create the condes tables if requested */
ConDesCreate ();
+ /* Process data from the config file */
+ CfgProcess ();
+
/* Assign start addresses for the segments, define linker symbols. The
* function will return the number of memory area overflows (zero on
* success).
lineinfo.o \
main.o \
mapfile.o \
+ memarea.o \
o65.o \
objdata.o \
objfile.o \
lineinfo.obj \
main.obj \
mapfile.obj \
+ memarea.obj \
o65.obj \
objdata.obj \
objfile.obj \
--- /dev/null
+/*****************************************************************************/
+/* */
+/* memarea.c */
+/* */
+/* Memory area definition for the ld65 linker */
+/* */
+/* */
+/* */
+/* (C) 2010, Ullrich von Bassewitz */
+/* Roemerstrasse 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. */
+/* */
+/*****************************************************************************/
+
+
+
+/* common */
+#include "xmalloc.h"
+
+/* ld65 */
+#include "memarea.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+MemoryArea* NewMemoryArea (unsigned Name)
+/* Create a new memory area and insert it into the list */
+{
+ /* Allocate memory */
+ MemoryArea* M = xmalloc (sizeof (MemoryArea));
+
+ /* Initialize the fields ... */
+ M->Name = Name;
+ M->Attr = 0;
+ M->Flags = 0;
+ M->StartExpr = 0;
+ M->Start = 0;
+ M->SizeExpr = 0;
+ M->Size = 0;
+ M->FillLevel = 0;
+ M->FillVal = 0;
+ M->Relocatable = 0;
+ InitCollection (&M->SegList);
+ M->F = 0;
+
+ /* ...and return it */
+ return M;
+}
+
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* memarea.h */
+/* */
+/* Memory area definition for the ld65 linker */
+/* */
+/* */
+/* */
+/* (C) 2010, Ullrich von Bassewitz */
+/* Roemerstrasse 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 MEMAREA_H
+#define MEMAREA_H
+
+
+
+/* common */
+#include "coll.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Forwards for structures */
+struct ExprNode;
+struct File;
+
+/* Memory area entry */
+typedef struct MemoryArea MemoryArea;
+struct MemoryArea {
+ unsigned Name; /* Name index of the memory section */
+ unsigned Attr; /* Which values are valid? */
+ unsigned Flags; /* Set of bitmapped flags */
+ struct ExprNode* StartExpr; /* Expression for start address */
+ unsigned long Start; /* Start address */
+ struct ExprNode* SizeExpr; /* Expression for size */
+ unsigned long Size; /* Length of memory section */
+ unsigned long FillLevel; /* Actual fill level of segment */
+ unsigned char FillVal; /* Value used to fill rest of seg */
+ unsigned char Relocatable; /* Memory area is relocatable */
+ Collection SegList; /* List of segments for this area */
+ struct File* F; /* Output file for this area */
+};
+
+/* Memory flags */
+#define MF_DEFINE 0x0001 /* Define start and size */
+#define MF_FILL 0x0002 /* Fill segment */
+#define MF_RO 0x0004 /* Read only memory area */
+#define MF_OVERFLOW 0x0008 /* Memory area overflow */
+#define MF_PLACED 0x0010 /* Memory area was placed */
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+MemoryArea* NewMemoryArea (unsigned Name);
+/* Create a new memory area and insert it into the list */
+
+
+
+/* End of memarea.h */
+
+#endif
+
+
+
+
+
#include "fileio.h"
#include "global.h"
#include "lineinfo.h"
+#include "memarea.h"
#include "o65.h"
#include "spool.h"
O65Desc* D; /* File format descriptor */
long Val; /* The offset value */
int TooComplex; /* Expression too complex */
- Memory* MemRef; /* Memory reference if any */
+ MemoryArea* MemRef; /* Memory reference if any */
Segment* SegRef; /* Segment reference if any */
Section* SecRef; /* Section reference if any */
ExtSym* ExtRef; /* External reference if any */
*/
{
/* Get the memory area from the expression */
- Memory* M = ED->MemRef;
+ MemoryArea* M = ED->MemRef;
/* Remember the "nearest" segment and its offset */
Segment* Nearest = 0;
D->ZPCount = 0;
/* Walk over the memory list */
- for (I = 0; I < CollCount (&F->MemList); ++I) {
+ for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
/* Get this entry */
- Memory* M = CollAtUnchecked (&F->MemList, I);
+ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I);
/* Walk through the segment list and count the segment types */
unsigned J;
/* Walk again through the list and setup the segment arrays */
TextIdx = DataIdx = BssIdx = ZPIdx = 0;
- for (I = 0; I < CollCount (&F->MemList); ++I) {
+ for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
/* Get this entry */
- Memory* M = CollAtUnchecked (&F->MemList, I);
+ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I);
/* Walk over the segment list and check the segment types */
unsigned J;
S->AddrSize = AddrSize;
S->ReadOnly = 0;
S->Relocatable = 0;
+ S->Placed = 0;
S->Dumped = 0;
/* Insert the segment into the segment list and assign the segment id */
/* Write the data from the given segment to a file. For expressions, F is
* called (see description of SegWriteFunc above).
*/
-{
+{
Section* Sec;
int Sign;
unsigned long Offs = 0;
unsigned char AddrSize; /* Address size of segment */
unsigned char ReadOnly; /* True for readonly segments (config) */
unsigned char Relocatable; /* True if the segment is relocatable */
+ unsigned char Placed; /* Did we place this segment already? */
unsigned char Dumped; /* Did we dump this segment? */
};