case CFGTOK_EXPORT:
/* We expect an identifier */
CfgAssureIdent ();
+ /* Check if the export symbol is also defined as an import. */
+ if (O65GetImport (O65FmtDesc, CfgSVal) != 0) {
+ CfgError ("Exported symbol `%s' cannot be an import", 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.
case CFGTOK_IMPORT:
/* We expect an identifier */
CfgAssureIdent ();
- /* 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, CfgSVal) != 0) {
- CfgError ("Duplicate imported symbol: `%s'", CfgSVal);
- }
- /* Insert the symbol into the table */
- O65SetImport (O65FmtDesc, CfgSVal);
+ /* Check if the imported symbol is also defined as an export. */
+ if (O65GetExport (O65FmtDesc, CfgSVal) != 0) {
+ CfgError ("Imported symbol `%s' cannot be an export", 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, CfgSVal) != 0) {
+ CfgError ("Duplicate imported symbol: `%s'", CfgSVal);
+ }
+ /* Insert the symbol into the table */
+ O65SetImport (O65FmtDesc, CfgSVal);
break;
case CFGTOK_TYPE:
/* Structure describing the format */
struct O65Desc {
- O65Header Header; /* File header */
+ O65Header Header; /* File header */
O65Option* Options; /* List of file options */
ExtSymTab* Exports; /* Table with exported symbols */
ExtSymTab* Imports; /* Table with imported symbols */
/*****************************************************************************/
-/* Helper functions */
+/* Helper functions */
/*****************************************************************************/
+static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D)
+/* Initialize an ExprDesc structure for use with O65ParseExpr */
+{
+ ED->D = D;
+ ED->Val = 0;
+ ED->TooComplex = 0;
+ ED->SegRef = 0;
+ ED->ExtRef = 0;
+ return ED;
+}
+
+
+
static void WriteSize (const O65Desc* D, unsigned long Val)
/* Write a "size" word to the file */
{
- if (D->Header.Mode & MF_SIZE_32BIT) {
- Write32 (D->F, Val);
- } else {
- Write16 (D->F, (unsigned) Val);
+ switch (D->Header.Mode & MF_SIZE_MASK) {
+ case MF_SIZE_16BIT: Write16 (D->F, (unsigned) Val); break;
+ case MF_SIZE_32BIT: Write32 (D->F, Val); break;
+ default: Internal ("Invalid size in header: %04X", D->Header.Mode);
}
}
}
} else {
MarkExport (E);
- O65ParseExpr (E->Expr, D, Sign);
+ O65ParseExpr (E->Expr, D, Sign);
UnmarkExport (E);
}
break;
/*****************************************************************************/
-/* Subroutines to write o65 sections */
+/* Subroutines to write o65 sections */
/*****************************************************************************/
Expr = E->Left;
}
- /* Initialize the descriptor for expression parsing */
- ED.D = D;
- ED.Val = 0;
- ED.TooComplex = 0;
- ED.SegRef = 0;
- ED.ExtRef = 0;
-
/* Recursively collect information about this expression */
- O65ParseExpr (Expr, &ED, 1);
+ O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
/* We cannot handle both, an imported symbol and a segment ref */
if (ED.SegRef != 0 && ED.ExtRef != 0) {
static void O65WriteImports (O65Desc* D)
/* Write the list of imported symbols to the O65 file */
{
- const ExtSym* E;
+ const ExtSym* S;
- /* Write the number of external symbols */
+ /* Write the number of imports */
WriteSize (D, ExtSymCount (D->Imports));
/* Write out the symbol names, zero terminated */
- E = ExtSymList (D->Imports);
- while (E) {
- /* Get the name */
- const char* Name = ExtSymName (E);
- /* And write it to the output file */
- WriteData (D->F, Name, strlen (Name) + 1);
- /* Next symbol */
- E = ExtSymNext (E);
+ S = ExtSymList (D->Imports);
+ while (S) {
+ /* Get the name */
+ const char* Name = ExtSymName (S);
+ /* And write it to the output file */
+ WriteData (D->F, Name, strlen (Name) + 1);
+ /* Next symbol */
+ S = ExtSymNext (S);
}
}
static void O65WriteExports (O65Desc* D)
/* Write the list of exports */
{
- /* Since ld65 creates exectutables, not object files, we do not have
- * exports. This may change if we support writing shared libraries...
- */
- WriteSize (D, 0);
+ const ExtSym* S;
+
+ /* Write the number of exports */
+ WriteSize (D, ExtSymCount (D->Exports));
+
+ /* Write out the symbol information */
+ S = ExtSymList (D->Exports);
+ while (S) {
+
+ ExprNode* Expr;
+ unsigned char SegmentID;
+ ExprDesc ED;
+
+ /* Get the name */
+ const char* Name = ExtSymName (S);
+
+ /* Get the export for this symbol. We've checked before that this
+ * 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);
+ if (E == 0 || IsUnresolvedExport (E)) {
+ Internal ("Unresolved export `%s' found in O65WriteExports", Name);
+ }
+
+ /* Get the expression for the symbol */
+ Expr = E->Expr;
+
+ /* Recursively collect information about this expression */
+ O65ParseExpr (Expr, InitExprDesc (&ED, D), 1);
+
+ /* We cannot handle expressions with imported symbols here */
+ if (ED.ExtRef != 0) {
+ ED.TooComplex = 1;
+ }
+
+ /* Bail out if we cannot handle the expression */
+ if (ED.TooComplex) {
+ Error ("Expression for symbol `%s' is too complex", Name);
+ }
+
+ /* Determine the segment id for the expression */
+ if (ED.SegRef == 0) {
+ /* Absolute value */
+ SegmentID = O65SEG_ABS;
+ } else {
+ /* Segment reference. Search for the segment and map it to it's
+ * o65 segmentID
+ */
+ const SegDesc* Seg = O65FindSeg (D, ED.SegRef->Seg);
+ if (Seg == 0) {
+ /* For some reason, we didn't find this segment in the list of
+ * segments written to the o65 file.
+ */
+ Error ("Segment for symbol `%s' is undefined", Name);
+ }
+ SegmentID = O65SegType (Seg);
+ }
+
+ /* Write the name to the output file */
+ WriteData (D->F, Name, strlen (Name) + 1);
+
+ /* Output the segment id followed by the literal value */
+ Write8 (D->F, SegmentID);
+ WriteSize (D, ED.Val);
+
+ /* Next symbol */
+ S = ExtSymNext (S);
+ }
}
void O65SetExport (O65Desc* D, const char* Ident)
/* Set an exported identifier */
{
+ /* Get the export for this symbol and check if it does exist and is
+ * a resolved symbol.
+ */
+ Export* E = FindExport (Ident);
+ if (E == 0 || IsUnresolvedExport (E)) {
+ Error ("Unresolved export: `%s'", Ident);
+ }
+
/* Insert the entry into the table */
NewExtSym (D->Exports, Ident);
}