/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdlib.h>
#include <stdarg.h>
+/* common */
+#include "cmdline.h"
+
+/* ar65 */
#include "error.h"
{
va_list ap;
va_start (ap, Format);
- fprintf (stderr, "Warning: ");
+ fprintf (stderr, "%s: Warning: ", ProgName);
vfprintf (stderr, Format, ap);
putc ('\n', stderr);
va_end (ap);
{
va_list ap;
va_start (ap, Format);
- fprintf (stderr, "Error: ");
+ fprintf (stderr, "%s: Error: ", ProgName);
vfprintf (stderr, Format, ap);
putc ('\n', stderr);
va_end (ap);
{
va_list ap;
va_start (ap, Format);
- fprintf (stderr, "Internal error: ");
+ fprintf (stderr, "%s: Internal error: ", ProgName);
vfprintf (stderr, Format, ap);
putc ('\n', stderr);
va_end (ap);
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* A hash table entry */
-typedef struct HashEntry HashEntry;
+typedef struct HashEntry HashEntry;
struct HashEntry {
HashEntry* Next; /* Next in list */
unsigned Module; /* Module index */
/* */
/* */
/* */
-/* (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 */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, Count);
while (Count--) {
- unsigned char Tag;
const char* Name;
- /* Get the export tag */
- Tag = *Exports++;
+ /* Get the export tag and skip the address size */
+ unsigned char Type = *Exports++;
+ ++Exports;
/* condes decls may follow */
- Exports += GET_EXP_CONDES_COUNT (Tag);
+ Exports += GET_EXP_CONDES_COUNT (Type);
/* Next thing is index of name of symbol */
Name = GetObjString (O, GetVar (&Exports));
/* Skip value of symbol */
- if (Tag & EXP_EXPR) {
+ if (Type & EXP_EXPR) {
/* Expression tree */
SkipExpr (&Exports);
} else {
/* */
/* */
/* */
-/* (C) 1998-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
case 'V':
fprintf (stderr,
- "ar65 V%u.%u.%u - (C) Copyright 1998-2001 Ullrich von Bassewitz\n",
+ "ar65 V%u.%u.%u - (C) Copyright 1998-2003 Ullrich von Bassewitz\n",
VER_MAJOR, VER_MINOR, VER_PATCH);
break;
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
H->StrPoolSize = Read32 (Obj);
H->AssertOffs = Read32 (Obj);
H->AssertSize = Read32 (Obj);
+ H->ScopeOffs = Read32 (Obj);
+ H->ScopeSize = Read32 (Obj);
}
Write32 (Obj, H->StrPoolOffs);
Write32 (Obj, H->StrPoolSize);
Write32 (Obj, H->AssertOffs);
- Write32 (Obj, H->AssertSize);
+ Write32 (Obj, H->AssertSize);
+ Write32 (Obj, H->ScopeOffs);
+ Write32 (Obj, H->ScopeSize);
}
H.LineInfoOffs = LibCopyTo (Obj, H.LineInfoSize) - O->Start;
fseek (Obj, H.AssertOffs, SEEK_SET);
H.AssertOffs = LibCopyTo (Obj, H.AssertSize) - O->Start;
+ fseek (Obj, H.ScopeOffs, SEEK_SET);
+ H.ScopeOffs = LibCopyTo (Obj, H.ScopeSize) - O->Start;
/* Calculate the amount of data written */
O->Size = ftell (NewLib) - O->Start;
#include "addrsize.h"
/* ca65 */
-#include "global.h"
+#include "global.h"
unsigned char DbgSyms = 0; /* Add debug symbols */
unsigned char Listing = 0; /* Create listing file */
unsigned char LineCont = 0; /* Allow line continuation */
-unsigned char DefAddrSize = ADDR_SIZE_ABS; /* Default address size */
-
+
/* Emulation features */
unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */
unsigned char NoColonLabels = 0; /* Allow labels without a colon */
extern unsigned char DbgSyms; /* Add debug symbols */
extern unsigned char Listing; /* Create listing file */
extern unsigned char LineCont; /* Allow line continuation */
-extern unsigned char DefAddrSize; /* Default address size */
/* Emulation features */
extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */
#include "addrsize.h"
#include "chartype.h"
#include "cmdline.h"
+#include "mmodel.h"
#include "print.h"
#include "target.h"
#include "tgttrans.h"
long Val;
char SymName [MAX_STR_LEN+1];
SymEntry* Sym;
+ ExprNode* Expr;
/* The symbol must start with a character or underline */
AbEnd ("`%s' is already defined", SymName);
}
+ /* Generate an expression for the symbol */
+ Expr = GenLiteralExpr (Val);
+
/* Mark the symbol as defined */
- SymDef (Sym, GenLiteralExpr (Val), ADDR_SIZE_DEFAULT, SF_NONE);
+ SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE);
}
-static void OptMemoryModel (const char* Opt attribute ((unused)), const char* Arg)
+static void OptMemoryModel (const char* Opt, const char* Arg)
/* Set the memory model */
{
- if (strcmp (Arg, "near") == 0) {
- DefAddrSize = ADDR_SIZE_ABS;
- } else if (strcmp (Arg, "far") == 0) {
- DefAddrSize = ADDR_SIZE_FAR;
- } else {
+ mmodel_t M;
+
+ /* Check the current memory model */
+ if (MemoryModel != MMODEL_UNKNOWN) {
+ AbEnd ("Cannot use option `%s' twice", Opt);
+ }
+
+ /* Translate the memory model name and check it */
+ M = FindMemoryModel (Arg);
+ if (M == MMODEL_UNKNOWN) {
AbEnd ("Unknown memory model: %s", Arg);
+ } else if (M == MMODEL_HUGE) {
+ AbEnd ("Unsupported memory model: %s", Arg);
}
+
+ /* Set the memory model */
+ SetMemoryModel (M);
}
}
}
+ /* If no memory model was given, use the default */
+ if (MemoryModel == MMODEL_UNKNOWN) {
+ MemoryModel = MMODEL_NEAR;
+ }
+
/* Intialize the target translation tables */
TgtTranslateInit ();
+ /* Initialize the segments */
+ InitSegments ();
+
/* Initialize the scanner, open the input file */
InitScanner (InFile);
0, /* 32: Offset to string pool */
0, /* 32: Size of string pool */
0, /* 32: Offset to assertion table */
- 0 /* 32: Size of assertion table */
+ 0, /* 32: Size of assertion table */
+ 0, /* 32: Offset into scope table */
+ 0, /* 32: Size of scope table */
};
ObjWrite32 (Header.StrPoolSize);
ObjWrite32 (Header.AssertOffs);
ObjWrite32 (Header.AssertSize);
+ ObjWrite32 (Header.ScopeOffs);
+ ObjWrite32 (Header.ScopeSize);
}
+void ObjStartScopes (void)
+/* Mark the start of the scope table */
+{
+ Header.ScopeOffs = ftell (F);
+}
+
+
+
+void ObjEndScopes (void)
+/* Mark the end of the scope table */
+{
+ Header.ScopeSize = ftell (F) - Header.ScopeOffs;
+}
+
+
+
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void ObjEndAssertions (void);
/* Mark the end of the assertion table */
+void ObjStartScopes (void);
+/* Mark the start of the scope table */
+
+void ObjEndScopes (void);
+/* Mark the end of the scope table */
+
/* End of objfile.h */
#include <errno.h>
/* common */
+#include "mmodel.h"
#include "segnames.h"
#include "xmalloc.h"
+void InitSegments (void)
+/* Initialize segments */
+{
+ /* Initialize segment sizes. The segment definitions do already contain
+ * the correct values for the default case (near), so we must only change
+ * things that should be different.
+ */
+ switch (MemoryModel) {
+
+ case MMODEL_NEAR:
+ break;
+
+ case MMODEL_FAR:
+ CodeSegDef.AddrSize = ADDR_SIZE_FAR;
+ break;
+
+ case MMODEL_HUGE:
+ CodeSegDef.AddrSize = ADDR_SIZE_FAR;
+ DataSegDef.AddrSize = ADDR_SIZE_FAR;
+ BssSegDef.AddrSize = ADDR_SIZE_FAR;
+ RODataSegDef.AddrSize = ADDR_SIZE_FAR;
+ break;
+
+ default:
+ Internal ("Invalid memory model: %d", MemoryModel);
+ }
+}
+
+
+
void WriteSegments (void)
/* Write the segment data to the object file */
{
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void SegDump (void);
/* Dump the contents of all segments */
+void InitSegments (void);
+/* Initialize segments */
+
void WriteSegments (void);
/* Write the segment data to the object file */
/* Set the symbol value */
S->V.Expr = Expr;
- /* If the symbol is marked as global, export it */
+ /* If the symbol is marked as global, export it. Address size is checked
+ * below.
+ */
if (S->Flags & SF_GLOBAL) {
- S->ExportSize = S->AddrSize;
S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
}
/* Use the real size of the symbol */
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
- PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported as %s",
+ /* We're exporting a symbol smaller than it actually is */
+ PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
}
- /* If the symbol is a ZP symbol, check if the value is in correct range */
- if (S->AddrSize == ADDR_SIZE_ZP) {
- /* Already marked as ZP symbol by some means */
- if (!IsByteExpr (Expr)) {
- Error ("Range error");
- }
- }
-
/* If this is not a local symbol, remember it as the last global one */
if (!IsLocalNameId (S->Name)) {
SymLast = S;
return;
}
- /* If no address size is given, use the default address size */
+ /* If no address size is given, use the address size of the enclosing
+ * segment.
+ */
if (AddrSize == ADDR_SIZE_DEFAULT) {
- AddrSize = DefAddrSize;
+ AddrSize = GetCurrentSegAddrSize ();
}
- /* If the symbol is marked as import or global, check the symbol flags,
- * then do silently remove the global flag
+ /* If the symbol is marked as import or global, check the address size,
+ * then do silently remove the global flag.
*/
if (S->Flags & SF_IMPORT) {
if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
}
}
if (S->Flags & SF_GLOBAL) {
- if (S->AddrSize != ADDR_SIZE_DEFAULT && S->AddrSize != AddrSize) {
+ S->Flags &= ~SF_GLOBAL;
+ if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
- S->Flags &= ~SF_GLOBAL;
}
/* Set the symbol data */
return;
}
- /* If the symbol was marked as global before, make it an export */
+ /* If the symbol was marked as global before, remove the global flag and
+ * proceed, but check the address size.
+ */
if (S->Flags & SF_GLOBAL) {
- S->ExportSize = S->AddrSize;
+ if (AddrSize != S->ExportSize) {
+ Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ }
S->Flags &= ~SF_GLOBAL;
}
- /* If the symbol was already marked as an export, check if this was done
- * specifiying the same address size. If the old spec had no explicit
- * address size, use the new one.
+ /* If the symbol was already marked as an export, but wasn't defined
+ * before, the address sizes in both definitions must match.
*/
- if (S->Flags & SF_EXPORT) {
- if (S->ExportSize == ADDR_SIZE_DEFAULT) {
- S->ExportSize = AddrSize;
- } else if (AddrSize == ADDR_SIZE_DEFAULT) {
- AddrSize = S->ExportSize;
- }
- if (S->ExportSize != ADDR_SIZE_DEFAULT && S->ExportSize != AddrSize) {
+ if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
+ if (S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
}
/* No export size given, use the real size of the symbol */
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
- Warning (1, "Symbol `%s' is %s but exported as %s",
+ /* We're exporting a symbol smaller than it actually is */
+ Warning (1, "Symbol `%s' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
return;
}
- /* If the symbol is already marked as import or export, check the
- * size of the definition, then bail out.
+ /* If the symbol is already marked as import, the address size must match.
+ * Apart from that, ignore the global declaration.
*/
if (S->Flags & SF_IMPORT) {
- if (AddrSize != ADDR_SIZE_DEFAULT && AddrSize != S->AddrSize) {
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ /* Use the size of the current segment */
+ AddrSize = GetCurrentSegAddrSize ();
+ }
+ if (AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
return;
}
+
+ /* If the symbol is already an export: If it is not defined, the address
+ * sizes must match.
+ */
if (S->Flags & SF_EXPORT) {
- /* If the old symbol had no explicit address size spec, use the
- * new one.
- */
- if (S->ExportSize == ADDR_SIZE_DEFAULT) {
- S->ExportSize = AddrSize;
+ if ((S->Flags & SF_DEFINED) == 0) {
+ /* Symbol is undefined */
+ if (AddrSize != S->ExportSize) {
+ Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ }
+ } else if (AddrSize != ADDR_SIZE_DEFAULT) {
+ /* Symbol is defined and address size given */
+ if (AddrSize != S->ExportSize) {
+ Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ }
}
+ return;
+ }
+
+ /* If the symbol is already marked as global, the address size must match.
+ * Use the ExportSize here, since it contains the actual address size
+ * passed to this function.
+ */
+ if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
return;
}
- /* If the symbol is already defined, export it. Otherwise mark it as
- * global.
+ /* If we come here, the symbol was neither declared as export, import or
+ * global before. Check if it is already defined, in which case it will
+ * become an export. If it is not defined, mark it as global and remember
+ * the given address sizes.
*/
if (S->Flags & SF_DEFINED) {
/* The symbol is defined, export it */
/* No export size given, use the real size of the symbol */
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
- Warning (1, "Symbol `%s' is %s but exported as %s",
+ /* We're exporting a symbol smaller than it actually is */
+ Warning (1, "Symbol `%s' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
S->Flags |= (SF_EXPORT | Flags);
- S->ExportSize = AddrSize;
} else {
- S->Flags |= (SF_GLOBAL | Flags);
+ /* Since we don't know if the symbol will get exported or imported,
+ * remember two different address sizes: One for an import in AddrSize,
+ * and the other one for an export in ExportSize.
+ */
S->AddrSize = AddrSize;
+ if (S->AddrSize == ADDR_SIZE_DEFAULT) {
+ /* Use the size of the current segment */
+ S->AddrSize = GetCurrentSegAddrSize ();
+ }
+ S->ExportSize = AddrSize;
+ S->Flags |= (SF_GLOBAL | Flags);
}
}
* priority value is the same as the old one.
*/
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
- if (S->ConDesPrio[Type] != Prio) {
- Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
- }
+ if (S->ConDesPrio[Type] != Prio) {
+ Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
+ }
}
S->ConDesPrio[Type] = Prio;
#include "addrsize.h"
#include "check.h"
#include "hashstr.h"
+#include "mmodel.h"
#include "symdefs.h"
#include "xmalloc.h"
if (AutoImport) {
/* Mark as import, will be indexed later */
S->Flags |= SF_IMPORT;
+ /* Use the address size for code */
+ S->AddrSize = CodeAddrSize;
} else {
/* Error */
PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
if ((S->Flags & (SF_TRAMPOLINE | SF_IMPORT)) == SF_IMPORT &&
(S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
- if (S->AddrSize == ADDR_SIZE_ZP) {
- ObjWrite8 (IMP_ZP);
- } else {
- ObjWrite8 (IMP_ABS);
- }
+ ObjWrite8 (S->AddrSize);
ObjWriteVar (S->Name);
ObjWritePos (&S->Pos);
}
/* Get the expression bits */
unsigned char ExprMask = SymIsConst (S, &ConstVal)? EXP_CONST : EXP_EXPR;
- ExprMask |= (S->ExportSize == ADDR_SIZE_ZP)? EXP_ZP : EXP_ABS;
ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
/* Count the number of ConDes types */
}
}
- /* Write the type */
+ /* Write the type and the export size */
ObjWrite8 (ExprMask);
+ ObjWrite8 (S->ExportSize);
/* Write any ConDes declarations */
if (GET_EXP_CONDES_COUNT (ExprMask) > 0) {
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
/* Constant value */
- ObjWrite32 (ConstVal);
+ ObjWrite32 (ConstVal);
} else {
/* Expression involved */
WriteExpr (S->V.Expr);
/* Check if debug info is requested */
if (DbgSyms) {
- /* Walk through the list and count the symbols */
- Count = 0;
- S = SymList;
- while (S) {
- if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
- ++Count;
- }
- S = S->List;
- }
+ /* Walk through the list and count the symbols */
+ Count = 0;
+ S = SymList;
+ while (S) {
+ if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
+ ++Count;
+ }
+ S = S->List;
+ }
- /* Write the symbol count to the list */
+ /* Write the symbol count to the list */
ObjWriteVar (Count);
/* Walk through list and write all symbols to the file */
- S = SymList;
- while (S) {
- if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
+ S = SymList;
+ while (S) {
+ if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
long ConstVal;
/* Get the expression bits */
unsigned char ExprMask = (SymIsConst (S, &ConstVal))? EXP_CONST : EXP_EXPR;
- ExprMask |= (S->AddrSize == ADDR_SIZE_ZP)? EXP_ZP : EXP_ABS;
ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
/* Write the type */
ObjWrite8 (ExprMask);
+ /* Write the address size */
+ ObjWrite8 (S->AddrSize);
+
/* Write the name */
ObjWriteVar (S->Name);
+void WriteScopes (void)
+/* Write the scope table to the object file */
+{
+ /* Tell the object file module that we're about to start the scopes */
+ ObjStartScopes ();
+
+ /* For now ...*/
+ ObjWriteVar (0);
+
+ /* Done writing the scopes */
+ ObjEndScopes ();
+}
+
/* Attach this label to the code entry */
CE_AttachLabel (E, L);
- }
+ }
/* Return the label */
return L;
* segment before outputing the function label.
*/
if (Func) {
+ /* Get the function descriptor */
+ const FuncDesc* D = GetFuncDesc (Func->Type);
CS_PrintFunctionHeader (S, F);
- fprintf (F, ".segment\t\"%s\"\n\n.proc\t_%s\n\n", S->SegName, Func->Name);
+ fprintf (F, ".segment\t\"%s\"\n\n.proc\t_%s", S->SegName, Func->Name);
+ if (D->Flags & FD_NEAR) {
+ fputs (": near", F);
+ } else if (D->Flags & FD_FAR) {
+ fputs (": far", F);
+ }
+ fputs ("\n\n", F);
}
}
*/
{
if (S->Func) {
- fprintf (F, "\n.endproc\n\n");
+ fputs ("\n.endproc\n\n", F);
}
}
/* If debug info is enabled, terminate the last line number information */
if (DebugInfo) {
- fprintf (F, "\t.dbg\tline\n");
+ fputs ("\t.dbg\tline\n", F);
}
}
break;
}
if (J->RI->Out2.RegA != Regs.RegA) {
- Regs.RegA = UNKNOWN_REGVAL;
+ Regs.RegA = UNKNOWN_REGVAL;
}
if (J->RI->Out2.RegX != Regs.RegX) {
Regs.RegX = UNKNOWN_REGVAL;
/* Check the previous instruction */
switch (P->OPC) {
- case OP65_ADC:
+ case OP65_ADC:
case OP65_AND:
case OP65_DEA:
case OP65_EOR:
case OP65_CPY:
/* If this is an immidiate compare, the Y register has
* the value of the compare later.
- */
+ */
if (CE_KnownImm (P)) {
if (BC == BC_EQ) {
E->RI->Out2.RegY = (unsigned char)P->Num;
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
-/* EMail: uz@musoftware.de */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* Print a comment with the function signature */
PrintType (F, GetFuncReturn (Type));
+ if (D->Flags & FD_NEAR) {
+ fprintf (F, " __near__");
+ }
+ if (D->Flags & FD_FAR) {
+ fprintf (F, " __far__");
+ }
if (D->Flags & FD_FASTCALL) {
fprintf (F, " __fastcall__");
}
return CF_LONG | CF_UNSIGNED;
case T_FLOAT:
- case T_DOUBLE:
+ case T_DOUBLE:
/* These two are identical in the backend */
return CF_FLOAT;
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+static unsigned FunctionModifierFlags (void)
+/* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */
+{
+ /* Read the flags */
+ unsigned Flags = FD_NONE;
+ while (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
+
+ /* Get the flag bit for the next token */
+ unsigned F = FD_NONE;
+ switch (CurTok.Tok) {
+ case TOK_FASTCALL: F = FD_FASTCALL; break;
+ case TOK_NEAR: F = FD_NEAR; break;
+ case TOK_FAR: F = FD_FAR; break;
+ default: Internal ("Unexpected token: %d", CurTok.Tok);
+ }
+
+ /* Remember the flag for this modifier */
+ if (Flags & F) {
+ Error ("Duplicate modifier");
+ }
+ Flags |= F;
+
+ /* Skip the token */
+ NextToken ();
+ }
+
+ /* Sanity check */
+ if ((Flags & (FD_NEAR | FD_FAR)) == (FD_NEAR | FD_FAR)) {
+ Error ("Cannot specify both, `__near__' and `__far__' modifiers");
+ Flags &= ~(FD_NEAR | FD_FAR);
+ }
+
+ /* Return the flags read */
+ return Flags;
+}
+
+
+
+static void ApplyFunctionModifiers (type* T, unsigned Flags)
+/* Apply a set of function modifier flags to a function */
+{
+ /* Get the function descriptor */
+ FuncDesc* F = GetFuncDesc (T);
+
+ /* Special check for __fastcall__ */
+ if ((Flags & FD_FASTCALL) != 0 && IsVariadicFunc (T)) {
+ Error ("Cannot apply `__fastcall__' to functions with "
+ "variable parameter list");
+ Flags &= ~FD_FASTCALL;
+ }
+
+ /* Add the flags */
+ F->Flags |= Flags;
+}
+
+
+
static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
/* Recursively process declarators. Build a type array in reverse order. */
{
-
+ /* Pointer to something */
if (CurTok.Tok == TOK_STAR) {
- type T = T_PTR;
+
+ type T;
+
+ /* Skip the star */
NextToken ();
+
/* Allow optional const or volatile qualifiers */
- T |= OptionalQualifiers (T_QUAL_NONE);
+ T = T_PTR | OptionalQualifiers (T_QUAL_NONE);
+
+ /* Parse the type, the pointer points to */
Decl (Spec, D, Mode);
+
*D->T++ = T;
return;
- } else if (CurTok.Tok == TOK_LPAREN) {
- NextToken ();
- Decl (Spec, D, Mode);
- ConsumeRParen ();
- } else if (CurTok.Tok == TOK_FASTCALL) {
+ }
+
+ /* Function modifiers */
+ if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
+
/* Remember the current type pointer */
type* T = D->T;
- /* Skip the fastcall token */
- NextToken ();
+
+ /* Read the flags */
+ unsigned Flags = FunctionModifierFlags ();
+
/* Parse the function */
Decl (Spec, D, Mode);
- /* Set the fastcall flag */
+
+ /* Check that we have a function */
if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
- Error ("__fastcall__ modifier applied to non function");
- } else if (IsVariadicFunc (T)) {
- Error ("Cannot apply __fastcall__ to functions with variable parameter list");
+ Error ("Function modifier applied to non function");
} else {
- FuncDesc* F = GetFuncDesc (T);
- F->Flags |= FD_FASTCALL;
- }
+ ApplyFunctionModifiers (T, Flags);
+ }
+
+ /* Done */
return;
+ }
+
+ if (CurTok.Tok == TOK_LPAREN) {
+ NextToken ();
+ Decl (Spec, D, Mode);
+ ConsumeRParen ();
} else {
/* Things depend on Mode now:
* - Mode == DM_NEED_IDENT means:
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
-/* Masks for the Flags field in FuncDesc */
+/* Masks for the Flags field in FuncDesc */
+#define FD_NONE 0x0000U /* No flags */
#define FD_IMPLICIT 0x0001U /* Implicitly declared function */
#define FD_EMPTY 0x0002U /* Function with empty param list */
#define FD_VOID_PARAM 0x0004U /* Function with a void param list */
#define FD_VARIADIC 0x0008U /* Function with variable param list */
#define FD_FASTCALL 0x0010U /* __fastcall__ function */
-#define FD_OLDSTYLE 0x0020U /* Old style (K&R) function */
-#define FD_OLDSTYLE_INTRET 0x0040U /* K&R func has implicit int return */
-#define FD_UNNAMED_PARAMS 0x0080U /* Function has unnamed params */
+#define FD_FAR 0x0020U /* __far__ function */
+#define FD_NEAR 0x0040U /* __near__ function */
+#define FD_OLDSTYLE 0x0100U /* Old style (K&R) function */
+#define FD_OLDSTYLE_INTRET 0x0200U /* K&R func has implicit int return */
+#define FD_UNNAMED_PARAMS 0x0400U /* Function has unnamed params */
/* Bits that must be ignored when comparing funcs */
#define FD_IGNORE (FD_IMPLICIT | FD_UNNAMED_PARAMS)
/* Defines for magic and version */
#define LIB_MAGIC 0x7A55616E
-#define LIB_VERSION 0x000A
+#define LIB_VERSION 0x000B
/* Size of an library file header */
#define LIB_HDR_SIZE 12
#include <string.h>
/* common */
+#include "addrsize.h"
#include "mmodel.h"
"huge",
};
+/* Address sizes for the segments */
+unsigned char CodeAddrSize = ADDR_SIZE_ABS;
+unsigned char DataAddrSize = ADDR_SIZE_ABS;
+unsigned char ZpAddrSize = ADDR_SIZE_ZP;
+
/*****************************************************************************/
+void SetMemoryModel (mmodel_t Model)
+/* Set the memory model updating the MemoryModel variables and the address
+ * sizes for the segments.
+ */
+{
+ /* Remember the memory model */
+ MemoryModel = Model;
+
+ /* Set the address sizes for the segments */
+ switch (MemoryModel) {
+
+ case MMODEL_NEAR:
+ /* Code: near, data: near */
+ CodeAddrSize = ADDR_SIZE_ABS;
+ DataAddrSize = ADDR_SIZE_ABS;
+ break;
+
+ case MMODEL_FAR:
+ /* Code: far, data: near */
+ CodeAddrSize = ADDR_SIZE_FAR;
+ DataAddrSize = ADDR_SIZE_ABS;
+ break;
+
+ case MMODEL_HUGE:
+ /* Code: far, data: far */
+ CodeAddrSize = ADDR_SIZE_FAR;
+ DataAddrSize = ADDR_SIZE_FAR;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Zeropage is always zeropage */
+ ZpAddrSize = ADDR_SIZE_ZP;
+}
+
+
/* Memory model in use */
extern mmodel_t MemoryModel;
-
-
+/* Address sizes for the segments */
+extern unsigned char CodeAddrSize;
+extern unsigned char DataAddrSize;
+extern unsigned char ZpAddrSize;
mmodel_t FindMemoryModel (const char* Name);
/* Find a memory model by name. Return MMODEL_UNKNOWN for an unknown name. */
+void SetMemoryModel (mmodel_t Model);
+/* Set the memory model updating the MemoryModel variables and the address
+ * sizes for the segments.
+ */
+
/* End of mmodel.h */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* Defines for magic and version */
#define OBJ_MAGIC 0x616E7A55
-#define OBJ_VERSION 0x000A
+#define OBJ_VERSION 0x000B
/* Size of an object file header */
-#define OBJ_HDR_SIZE (20*4)
+#define OBJ_HDR_SIZE (22*4)
/* Flag bits */
#define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */
unsigned long StrPoolSize; /* 32: Size of string pool */
unsigned long AssertOffs; /* 32: Offset to assertion table */
unsigned long AssertSize; /* 32: Size of assertion table */
+ unsigned long ScopeOffs; /* 32: Offset into scope table */
+ unsigned long ScopeSize; /* 32: Size of scope table */
};
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
-/* Import size */
-#define IMP_ABS 0x00 /* Import as normal value */
-#define IMP_ZP 0x01 /* Import as zero page symbol */
-#define IMP_MASK_SIZE 0x01 /* Size mask */
-
-#define IS_IMP_ABS(x) (((x) & IMP_MASK_SIZE) == IMP_ABS)
-#define IS_IMP_ZP(x) (((x) & IMP_MASK_SIZE) == IMP_ZP)
-
/* Number of module constructor/destructor declarations for an export */
#define EXP_CONDES_MASK 0x07
#define GET_EXP_CONDES_COUNT(x) ((x) & EXP_CONDES_MASK)
#define INC_EXP_CONDES_COUNT(x) ((x)++)
-/* Export size */
-#define EXP_ABS 0x00 /* Export as normal value */
-#define EXP_ZP 0x08 /* Export as zero page value */
-#define EXP_MASK_SIZE 0x08 /* Size mask */
-
-#define IS_EXP_ABS(x) (((x) & EXP_MASK_SIZE) == EXP_ABS)
-#define IS_EXP_ZP(x) (((x) & EXP_MASK_SIZE) == EXP_ZP)
-
/* Export value type */
#define EXP_CONST 0x00 /* Mask bit for const values */
#define EXP_EXPR 0x10 /* Mask bit for expr values */
-static DbgSym* NewDbgSym (unsigned char Type, ObjData* O)
+static DbgSym* NewDbgSym (unsigned char Type, unsigned char AddrSize, ObjData* O)
/* Create a new DbgSym and return it */
{
/* Allocate memory */
D->Expr = 0;
D->Name = 0;
D->Type = Type;
+ D->AddrSize = AddrSize;
/* Return the new entry */
return D;
DbgSym* ReadDbgSym (FILE* F, ObjData* O)
/* Read a debug symbol from a file, insert and return it */
{
- /* Read the type */
+ /* Read the type and address size */
unsigned char Type = Read8 (F);
+ unsigned char AddrSize = Read8 (F);
/* Create a new debug symbol */
- DbgSym* D = NewDbgSym (Type, O);
+ DbgSym* D = NewDbgSym (Type, AddrSize, O);
/* Read and assign the name */
D->Name = MakeGlobalStringId (O, ReadVar (F));
+
ExprNode* Expr; /* Expression (0 if not def'd) */
unsigned Name; /* Name */
unsigned char Type; /* Type of symbol */
+ unsigned char AddrSize; /* Address size of symbol */
};
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
#include <string.h>
/* common */
+#include "addrsize.h"
#include "check.h"
#include "coll.h"
#include "hashstr.h"
-static Export* NewExport (unsigned char Type, unsigned Name, ObjData* Obj);
+static Export* NewExport (unsigned char Type, unsigned char AddrSize,
+ unsigned Name, ObjData* Obj);
/* Create a new export and initialize it */
-static Import* NewImport (unsigned char Type, ObjData* Obj)
+static Import* NewImport (unsigned char AddrSize, ObjData* Obj)
/* Create a new import and initialize it */
{
/* Allocate memory */
I->Exp = 0;
I->Name = INVALID_STRING_ID;
I->Flags = 0;
- I->Type = Type;
+ I->AddrSize = AddrSize;
/* Return the new structure */
return I;
/* Search through the list in that slot and print matching duplicates */
if (HashTab[Hash] == 0) {
/* The slot is empty, we need to insert a dummy export */
- E = HashTab[Hash] = NewExport (0, Name, 0);
+ E = HashTab[Hash] = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0);
++ExpCount;
} else {
E = HashTab [Hash];
}
if (E->Next == 0) {
/* End of list an entry not found, insert a dummy */
- E->Next = NewExport (0, Name, 0);
+ E->Next = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0);
E = E->Next; /* Point to dummy */
++ExpCount; /* One export more */
break;
{
Import* I;
- /* Read the import type and check it */
- unsigned char Type = Read8 (F);
- if (Type != IMP_ZP && Type != IMP_ABS) {
- Error ("Unknown import type in module `%s': %02X",
- GetObjFileName (Obj), Type);
- }
+ /* Read the import address size */
+ unsigned char AddrSize = Read8 (F);
/* Create a new import */
- I = NewImport (Type, Obj);
+ I = NewImport (AddrSize, Obj);
/* Read the name */
I->Name = MakeGlobalStringId (Obj, ReadVar (F));
/* Read the file position */
ReadFilePos (F, &I->Pos);
+ /* Check the address size */
+ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) {
+ /* Beware: This function may be called in cases where the object file
+ * is not read completely into memory. In this case, the file list is
+ * invalid. Be sure not to access it in this case.
+ */
+ if (ObjHasFiles (I->Obj)) {
+ Error ("Invalid import size in for `%s', imported from %s(%lu): 0x%02X",
+ GetString (I->Name),
+ GetSourceFileName (I->Obj, I->Pos.Name),
+ I->Pos.Line,
+ I->AddrSize);
+ } else {
+ Error ("Invalid import size in for `%s', imported from %s: 0x%02X",
+ GetString (I->Name),
+ GetObjFileName (I->Obj),
+ I->AddrSize);
+ }
+ }
+
/* Return the new import */
return I;
}
-static Export* NewExport (unsigned char Type, unsigned Name, ObjData* Obj)
+static Export* NewExport (unsigned char Type, unsigned char AddrSize,
+ unsigned Name, ObjData* Obj)
/* Create a new export and initialize it */
{
/* Allocate memory */
E->ImpList = 0;
E->Expr = 0;
E->Type = Type;
+ E->AddrSize = AddrSize;
memset (E->ConDes, 0, sizeof (E->ConDes));
/* Return the new entry */
Export* ReadExport (FILE* F, ObjData* O)
/* Read an export from a file */
{
- unsigned char Type;
unsigned ConDesCount;
Export* E;
/* Read the type */
- Type = Read8 (F);
+ unsigned char Type = Read8 (F);
+
+ /* Read the address size */
+ unsigned char AddrSize = Read8 (F);
/* Create a new export without a name */
- E = NewExport (Type, INVALID_STRING_ID, O);
+ E = NewExport (Type, AddrSize, INVALID_STRING_ID, O);
/* Read the constructor/destructor decls if we have any */
ConDesCount = GET_EXP_CONDES_COUNT (Type);
/* Create an export for a literal date */
{
/* Create a new export */
- Export* E = NewExport (EXP_ABS | EXP_CONST | EXP_EQUATE, Name, 0);
+ Export* E = NewExport (EXP_CONST | EXP_EQUATE, ADDR_SIZE_ABS, Name, 0);
/* Assign the value */
E->Expr = LiteralExpr (Value, 0);
/* Create an relative export for a memory area offset */
{
/* Create a new export */
- Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
+ Export* E = NewExport (EXP_EXPR | EXP_LABEL, ADDR_SIZE_ABS, Name, 0);
/* Assign the value */
E->Expr = MemoryExpr (Mem, Offs, 0);
/* Create a relative export to a segment */
{
/* Create a new export */
- Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
+ Export* E = NewExport (EXP_EXPR | EXP_LABEL, Seg->AddrSize, Name, 0);
/* Assign the value */
E->Expr = SegmentExpr (Seg, Offs, 0);
/* Create a relative export to a section */
{
/* Create a new export */
- Export* E = NewExport (EXP_ABS | EXP_EXPR | EXP_LABEL, Name, 0);
+ Export* E = NewExport (EXP_EXPR | EXP_LABEL, Sec->AddrSize, Name, 0);
/* Assign the value */
E->Expr = SectionExpr (Sec, Offs, 0);
{
/* External with matching imports */
Import* Imp = E->ImpList;
- int ZP = IS_EXP_ZP (E->Type);
while (Imp) {
- if (ZP != IS_IMP_ZP (Imp->Type)) {
+ if (E->AddrSize != Imp->AddrSize) {
/* Export is ZP, import is abs or the other way round */
if (E->Obj) {
/* User defined export */
- Warning ("Type mismatch for `%s', export in "
+ Warning ("Address size mismatch for `%s', export in "
"%s(%lu), import in %s(%lu)",
GetString (E->Name),
GetSourceFileName (E->Obj, E->Pos.Name),
Imp->Pos.Line);
} else {
/* Export created by the linker */
- Warning ("Type mismatch for `%s', imported from %s(%lu)",
+ Warning ("Address size mismatch for `%s', imported from %s(%lu)",
GetString (E->Name),
GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
+static char GetAddrSizeCode (unsigned char AddrSize)
+/* Get a one char code for the address size */
+{
+ switch (AddrSize) {
+ case ADDR_SIZE_ZP: return 'Z';
+ case ADDR_SIZE_ABS: return 'A';
+ case ADDR_SIZE_FAR: return 'F';
+ case ADDR_SIZE_LONG: return 'L';
+ default:
+ Internal ("Invalid address size: %u", AddrSize);
+ }
+}
+
+
+
void PrintExportMap (FILE* F)
/* Print an export map to the given file */
{
GetExportVal (E),
E->ImpCount? 'R' : ' ',
IS_EXP_LABEL (E->Type)? 'L' : 'E',
- IS_EXP_ZP (E->Type)? 'Z' : ' ',
+ GetAddrSizeCode (E->AddrSize),
IS_EXP_CONDES (E->Type)? 'I' : ' ');
if (++Count == 2) {
Count = 0;
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
struct Export* Exp; /* Matching export for this import */
unsigned Name; /* Name if not in table */
unsigned char Flags; /* Generic flags */
- unsigned char Type; /* Type of import */
+ unsigned char AddrSize; /* Address size of import */
};
FilePos Pos; /* File position of definition */
ExprNode* Expr; /* Expression (0 if not def'd) */
unsigned char Type; /* Type of export */
+ unsigned char AddrSize; /* Address size of export */
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
};
/* End of exports.h */
#endif
-
+
/*****************************************************************************/
-/* */
+/* */
/* library.c */
-/* */
+/* */
/* Library data structures and helpers for the ld65 linker */
-/* */
-/* */
-/* */
+/* */
+/* */
+/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
O->Header.StrPoolSize = Read32 (Lib);
O->Header.AssertOffs = Read32 (Lib);
O->Header.AssertSize = Read32 (Lib);
+ O->Header.ScopeOffs = Read32 (Lib);
+ O->Header.ScopeSize = Read32 (Lib);
}
/* Read the assertions from the object file */
ObjReadAssertions (Lib, O->Start + O->Header.AssertOffs, O);
+ /* Read the scope table from the object file */
+ ObjReadScopes (Lib, O->Start + O->Header.ScopeOffs, O);
+
/* Seek to the start of the segment list and read the segments.
* This must be last, since the data here may reference other
* stuff.
O->Strings = 0;
O->AssertionCount = 0;
O->Assertions = 0;
+ O->ScopeCount = 0;
+ O->Scopes = 0;
/* Return the new entry */
return O;
/* Check the parameter */
if (Index >= O->FileCount) {
- Error ("Invalid file index (%u) in module `%s' (input file corrupt?)",
+ /* Error() will terminate the program */
+ Warning ("Invalid file index (%u) in module `%s' (input file corrupt?)",
Index, GetObjFileName (O));
+ return "[invalid]"; /* ### */
}
/* Return the name */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* common */
#include "coll.h"
+#include "inline.h"
#include "objdefs.h"
unsigned LibName; /* Name of library */
unsigned long MTime; /* Time of last modification */
ObjHeader Header; /* Header of file */
- unsigned long Start; /* Start offset of data in library */
+ unsigned long Start; /* Start offset of data in library */
unsigned Flags;
unsigned FileCount; /* Input file count */
struct FileInfo** Files; /* List of input files */
unsigned* Strings; /* List of global string indices */
unsigned AssertionCount; /* Count of module assertions */
struct Assertion** Assertions; /* List of module assertions */
+ unsigned ScopeCount; /* Count of scopes */
+ struct Scope** Scopes; /* List of scopes */
};
* file is NULL.
*/
+#if defined(HAVE_INLINE)
+INLINE int ObjHasFiles (const ObjData* O)
+/* Return true if the files list does exist */
+{
+ return (O != 0 && O->Files != 0);
+}
+#else
+# defined ObjHasFiles(O) ((O) != 0 && (O)->Files != 0)
+#endif
+
const char* GetSourceFileName (const ObjData* O, unsigned Index);
/* Get the name of the source file with the given index. If O is NULL, return
* "[linker generated]" as the file name.
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
H->StrPoolSize = Read32 (Obj);
H->AssertOffs = Read32 (Obj);
H->AssertSize = Read32 (Obj);
+ H->ScopeOffs = Read32 (Obj);
+ H->ScopeSize = Read32 (Obj);
}
+void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O)
+/* Read the scope table from a file at the given offset */
+{
+ unsigned I;
+
+ /* Seek to the correct position */
+ FileSetPos (F, Pos);
+
+ /* Read the data */
+ O->ScopeCount = ReadVar (F);
+ O->Scopes = xmalloc (O->ScopeCount * sizeof (O->Scopes[0]));
+ for (I = 0; I < O->ScopeCount; ++I) {
+ O->Scopes[I] = 0; /* ReadScope (F, O); ### not implemented */
+ }
+}
+
+
+
void ObjAdd (FILE* Obj, const char* Name)
/* Add an object file to the module list */
{
/* Read the assertions from the object file */
ObjReadAssertions (Obj, O->Header.AssertOffs, O);
+ /* Read the scope table from the object file */
+ ObjReadScopes (Obj, O->Header.ScopeOffs, O);
+
/* Read the segment list from the object file. This must be last, since
* the expressions stored in the code may reference segments or imported
* symbols.
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O);
/* Read the assertions from a file at the given offset */
+void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O);
+/* Read the scope table from a file at the given offset */
+
void ObjAdd (FILE* F, const char* Name);
/* Add an object file to the module list */
unsigned Count;
unsigned I;
- /* Adressing mode */
- TypeDesc[0] = '\0';
- switch (Flags & EXP_MASK_SIZE) {
- case EXP_ABS: strcat (TypeDesc, "EXP_ABS"); break;
- case EXP_ZP: strcat (TypeDesc, "EXP_ZP"); break;
- }
-
/* Type of expression */
+ TypeDesc[0] = '\0';
switch (Flags & EXP_MASK_VAL) {
- case EXP_CONST: strcat (TypeDesc, ",EXP_CONST"); break;
- case EXP_EXPR: strcat (TypeDesc, ",EXP_EXPR"); break;
+ case EXP_CONST: strcat (TypeDesc, "EXP_CONST"); break;
+ case EXP_EXPR: strcat (TypeDesc, "EXP_EXPR"); break;
}
/* Constructor/destructor declarations */
T = TypeDesc + strlen (TypeDesc);
Count = GET_EXP_CONDES_COUNT (Flags);
- if (Count > 0) {
+ if (Count > 0 && ConDes) {
T += sprintf (T, ",EXP_CONDES=");
for (I = 0; I < Count; ++I) {
unsigned Type = CD_GET_TYPE (ConDes[I]);
/* Read and print all imports */
for (I = 0; I < Count; ++I) {
- const char* TypeDesc;
-
/* Read the data for one import */
- unsigned char Type = Read8 (F);
- const char* Name = GetString (&StrPool, ReadVar (F));
- unsigned Len = strlen (Name);
+ unsigned char AddrSize = Read8 (F);
+ const char* Name = GetString (&StrPool, ReadVar (F));
+ unsigned Len = strlen (Name);
ReadFilePos (F, &Pos);
- /* Get a description for the type */
- switch (Type) {
- case IMP_ZP: TypeDesc = "IMP_ZP"; break;
- case IMP_ABS: TypeDesc = "IMP_ABS"; break;
- default: TypeDesc = "IMP_UNKNOWN"; break;
- }
-
/* Print the header */
printf (" Index:%27u\n", I);
/* Print the data */
- printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
+ printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
+ AddrSizeToStr (AddrSize));
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
}
unsigned long Value = 0;
int HaveValue;
- unsigned char Type;
unsigned char ConDes [CD_TYPE_COUNT];
const char* Name;
unsigned Len;
/* Read the data for one export */
- Type = Read8 (F);
+ unsigned char Type = Read8 (F);
+ unsigned char AddrSize = Read8 (F);
ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type));
Name = GetString (&StrPool, ReadVar (F));
Len = strlen (Name);
/* Print the data */
printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes));
+ printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
+ AddrSizeToStr (AddrSize));
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
if (HaveValue) {
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
for (I = 0; I < Count; ++I) {
unsigned long Value = 0;
- int HaveValue;
- unsigned char Type;
- unsigned char ConDes [CD_TYPE_COUNT];
- const char* Name;
- unsigned Len;
+ int HaveValue;
/* Read the data for one symbol */
- Type = Read8 (F);
- ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type));
- Name = GetString (&StrPool, ReadVar (F));
- Len = strlen (Name);
+ unsigned char Type = Read8 (F);
+ unsigned char AddrSize = Read8 (F);
+ const char* Name = GetString (&StrPool, ReadVar (F));
+ unsigned Len = strlen (Name);
if (IS_EXP_EXPR (Type)) {
SkipExpr (F);
HaveValue = 0;
printf (" Index:%27u\n", I);
/* Print the data */
- printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes));
+ printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, 0));
+ printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
+ AddrSizeToStr (AddrSize));
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
if (HaveValue) {
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
H->StrPoolSize = Read32 (F);
H->AssertOffs = Read32 (F);
H->AssertSize = Read32 (F);
+ H->ScopeOffs = Read32 (F);
+ H->ScopeSize = Read32 (F);
}