(void) Read32 (F);
}
+ /* Skip the size if necessary */
+ if (SYM_HAS_SIZE (Type)) {
+ (void) ReadVar (F);
+ }
+
/* Line info indices */
SkipLineInfoList (F);
}
int Anon = (CurTok.Tok != TOK_IDENT);
if (!Anon) {
/* Enter a new scope, then skip the name */
- SymEnterLevel (&CurTok.SVal, ST_ENUM, ADDR_SIZE_ABS);
+ SymEnterLevel (&CurTok.SVal, ST_ENUM, ADDR_SIZE_ABS, 0);
NextTok ();
}
static void OptListing (const char* Opt, const char* Arg)
/* Create a listing file */
-{
+{
/* Since the meaning of -l and --listing has changed, print an error if
* the filename is empty or begins with the option char.
*/
/* Enter the base lexical level. We must do that here, since we may
* define symbols using -D.
*/
- SymEnterLevel (&GlobalNameSpace, ST_GLOBAL, ADDR_SIZE_DEFAULT);
+ SymEnterLevel (&GlobalNameSpace, ST_GLOBAL, ADDR_SIZE_DEFAULT, 0);
/* Initialize the line infos. Must be done here, since we need line infos
* for symbol definitions.
{
StrBuf Name = STATIC_STRBUF_INITIALIZER;
unsigned char AddrSize;
+ SymEntry* Sym = 0;
- if (CurTok.Tok == TOK_IDENT) {
- SymEntry* Sym;
+ if (CurTok.Tok == TOK_IDENT) {
- /* The new scope has a name. Remember it. */
+ /* The new scope has a name. Remember it. */
SB_Copy (&Name, &CurTok.SVal);
/* Search for the symbol, generate a new one if needed */
}
/* Enter a new scope */
- SymEnterLevel (&Name, ST_PROC, AddrSize);
+ SymEnterLevel (&Name, ST_PROC, AddrSize, Sym);
/* Free memory for Name */
SB_Done (&Name);
AddrSize = OptionalAddrSize ();
/* Enter the new scope */
- SymEnterLevel (&Name, ST_SCOPE, AddrSize);
+ SymEnterLevel (&Name, ST_SCOPE, AddrSize, 0);
/* Free memory for Name */
SB_Done (&Name);
/* */
/* */
/* */
-/* (C) 2003-2008, Ullrich von Bassewit */
+/* (C) 2003-2011, Ullrich von Bassewit */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* The name of the symbol used to encode the size. The name of this entry is
* choosen so that it cannot be accessed by the user.
*/
-const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size");
+static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size");
+int IsSizeOfSymbol (const SymEntry* Sym)
+/* Return true if the given symbol is the one that encodes the size of some
+ * entity. Sym may also be a NULL pointer in which case false is returned.
+ */
+{
+ return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0);
+}
+
+
+
+SymEntry* FindSizeOfScope (SymTable* Scope)
+/* Get the size of a scope. The function returns the symbol table entry that
+ * encodes the size or NULL if there is no such entry.
+ */
+{
+ return SymFind (Scope, &SizeEntryName, SYM_FIND_EXISTING);
+}
+
+
+
+SymEntry* FindSizeOfSymbol (SymEntry* Sym)
+/* Get the size of a symbol table entry. The function returns the symbol table
+ * entry that encodes the size of the symbol or NULL if there is no such entry.
+ */
+{
+ return SymFindLocal (Sym, &SizeEntryName, SYM_FIND_EXISTING);
+}
+
+
+
SymEntry* GetSizeOfScope (SymTable* Scope)
/* Get the size of a scope. The function returns the symbol table entry that
* encodes the size, and will create a new entry if it does not exist.
/* */
/* */
/* */
-/* (C) 2003-2008, Ullrich von Bassewitz */
+/* (C) 2003-2011, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#ifndef SIZEOF_H
#define SIZEOF_H
-
+
/* common */
/*****************************************************************************/
-/* Data */
+/* Code */
/*****************************************************************************/
-extern const StrBuf SizeEntryName; /* Contains name of symbol with size */
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
+int IsSizeOfSymbol (const struct SymEntry* Sym);
+/* Return true if the given symbol is the one that encodes the size of some
+ * entity. Sym may also be a NULL pointer in which case false is returned.
+ */
+struct SymEntry* FindSizeOfScope (struct SymTable* Scope);
+/* Get the size of a scope. The function returns the symbol table entry that
+ * encodes the size or NULL if there is no such entry.
+ */
+struct SymEntry* FindSizeOfSymbol (struct SymEntry* Sym);
+/* Get the size of a symbol table entry. The function returns the symbol table
+ * entry that encodes the size of the symbol or NULL if there is no such entry.
+ */
struct SymEntry* GetSizeOfScope (struct SymTable* Scope);
/* Get the size of a scope. The function returns the symbol table entry that
int Anon = (CurTok.Tok != TOK_IDENT);
if (!Anon) {
/* Enter a new scope, then skip the name */
- SymEnterLevel (&CurTok.SVal, ST_STRUCT, ADDR_SIZE_ABS);
+ SymEnterLevel (&CurTok.SVal, ST_STRUCT, ADDR_SIZE_ABS, 0);
NextTok ();
/* Start at zero offset in the new scope */
Offs = 0;
ConsumeSep ();
/* Read until end of struct */
- while (CurTok.Tok != TOK_ENDSTRUCT &&
- CurTok.Tok != TOK_ENDUNION &&
+ while (CurTok.Tok != TOK_ENDSTRUCT &&
+ CurTok.Tok != TOK_ENDUNION &&
CurTok.Tok != TOK_EOF) {
long MemberSize;
long GetStructSize (SymTable* Struct)
/* Get the size of a struct or union */
{
- SymEntry* Sym = SymFind (Struct, &SizeEntryName, SYM_FIND_EXISTING);
- if (Sym == 0) {
+ SymEntry* SizeSym = FindSizeOfScope (Struct);
+ if (SizeSym == 0) {
Error ("Size of struct/union is unknown");
return 0;
} else {
- return GetSymVal (Sym);
+ return GetSymVal (SizeSym);
}
}
S->Left = 0;
S->Right = 0;
S->Childs = 0;
+ S->OwnerSym = 0;
S->SegRanges = AUTO_COLLECTION_INITIALIZER;
S->Flags = ST_NONE;
S->AddrSize = ADDR_SIZE_DEFAULT;
} else {
T->Right = S;
break;
- }
+ }
} else {
/* Duplicate scope name */
Internal ("Duplicate scope name: `%m%p'", Name);
-void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize)
+void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
+ unsigned char AddrSize, SymEntry* OwnerSym)
/* Enter a new lexical level */
{
/* Map a default address size to something real */
CurrentScope = RootScope = NewSymTable (0, ScopeName);
}
- /* Mark the scope as defined and set type and address size */
+ /* Mark the scope as defined and set type, address size and owner symbol */
CurrentScope->Flags |= ST_DEFINED;
CurrentScope->AddrSize = AddrSize;
CurrentScope->Type = Type;
+ CurrentScope->OwnerSym = OwnerSym;
/* If this is a scope that allows to emit data into segments, add segment
* ranges for all currently existing segments. Doing this for just a few
/* If we have segment ranges, the first one is the segment that was
* active, when the scope was opened. Set the size of the scope to the
- * number of data bytes emitted into this segment.
+ * number of data bytes emitted into this segment. If we have an owner
+ * symbol set the size of this symbol, too.
*/
if (CollCount (&CurrentScope->SegRanges) > 0) {
const SegRange* R = CollAtUnchecked (&CurrentScope->SegRanges, 0);
- DefSizeOfScope (CurrentScope, GetSegRangeSize (R));
+ unsigned long Size = GetSegRangeSize (R);
+ DefSizeOfScope (CurrentScope, Size);
+ if (CurrentScope->OwnerSym) {
+ DefSizeOfSymbol (CurrentScope->OwnerSym, Size);
+ }
}
/* Leave the scope */
/* The symbol is definitely undefined */
if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */
- LIError (&S->LineInfos,
+ LIError (&S->LineInfos,
"Exported symbol `%m%p' was never defined",
GetSymName (S));
} else {
S->AddrSize = CodeAddrSize;
} else {
/* Error */
- LIError (&S->LineInfos,
- "Symbol `%m%p' is undefined",
+ LIError (&S->LineInfos,
+ "Symbol `%m%p' is undefined",
GetSymName (S));
}
}
long ConstVal;
unsigned ExprMask = GetSymInfoFlags (S, &ConstVal);
+ /* Check if this symbol has a size. If so, remember it in the
+ * flags.
+ */
+ long Size;
+ SymEntry* SizeSym = FindSizeOfSymbol (S);
+ if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
+ ExprMask |= SYM_SIZE;
+ }
+
/* Count the number of ConDes types */
for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
WriteExpr (S->Expr);
}
+ /* If the symbol has a size, write it to the file */
+ if (SYM_HAS_SIZE (ExprMask)) {
+ ObjWriteVar (Size);
+ }
+
/* Write the line infos */
WriteLineInfo (&S->LineInfos);
}
Count = 0;
S = SymList;
while (S) {
- if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
+ if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL &&
+ !IsSizeOfSymbol (S)) {
S->DebugSymId = Count++;
}
S = S->List;
/* Write the symbol count to the list */
ObjWriteVar (Count);
- /* Walk through list and write all symbols to the file */
+ /* Walk through list and write all symbols to the file. Ignore size
+ * symbols.
+ */
S = SymList;
while (S) {
- if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
+ if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL &&
+ !IsSizeOfSymbol (S)) {
/* Get the expression bits and the value */
long ConstVal;
unsigned ExprMask = GetSymInfoFlags (S, &ConstVal);
+ /* Check if this symbol has a size. If so, remember it in the
+ * flags.
+ */
+ long Size;
+ SymEntry* SizeSym = FindSizeOfSymbol (S);
+ if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
+ ExprMask |= SYM_SIZE;
+ }
+
/* Write the type */
ObjWriteVar (ExprMask);
WriteExpr (S->Expr);
}
+ /* If the symbol has a size, write it to the file */
+ if (SYM_HAS_SIZE (ExprMask)) {
+ ObjWriteVar (Size);
+ }
+
/* Write the line infos */
WriteLineInfo (&S->LineInfos);
}
/* */
/* */
/* */
-/* (C) 1998-2010, Ullrich von Bassewitz */
+/* (C) 1998-2011, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* A symbol table */
typedef struct SymTable SymTable;
-struct SymTable {
+struct SymTable {
SymTable* Next; /* Pointer to next table in list */
SymTable* Left; /* Pointer to smaller entry */
SymTable* Right; /* Pointer to greater entry */
SymTable* Parent; /* Link to enclosing scope if any */
SymTable* Childs; /* Pointer to child scopes */
+ SymEntry* OwnerSym; /* Symbol that "owns" the scope */
Collection SegRanges; /* Segment ranges for this scope */
unsigned Id; /* Scope id */
unsigned short Flags; /* Symbol table flags */
-void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize);
+void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
+ unsigned char AddrSize, SymEntry* OwnerSym);
/* Enter a new lexical level */
void SymLeaveLevel (void);
#define LI_TYPE_ASM 0U /* Normal assembler source */
#define LI_TYPE_EXT 1U /* Externally supplied line info */
#define LI_TYPE_MACRO 2U /* Macro expansion */
+#define LI_TYPE_MACPARAM 3U /* Macro parameter expansion */
/* Make a combined value from type and count */
#define LI_MAKE_TYPE(T,C) ((T) | (((unsigned)(C)) << 2U))
/* Defines for magic and version */
#define OBJ_MAGIC 0x616E7A55
-#define OBJ_VERSION 0x000D
+#define OBJ_VERSION 0x000E
/* Size of an object file header */
#define OBJ_HDR_SIZE (22*4)
/* */
/* */
/* */
-/* (C) 1998-2010, Ullrich von Bassewitz */
+/* (C) 1998-2011, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#define SYM_GET_CONDES_COUNT(x) ((x) & SYM_CONDES_MASK)
#define SYM_INC_CONDES_COUNT(x) ((x)++)
+/* Size of symbol available? */
+#define SYM_SIZELESS 0x00U /* No symbol size available */
+#define SYM_SIZE 0x08U /* Symbol has a size */
+#define SYM_MASK_SIZE 0x08U /* Size mask */
+
+#define SYM_HAS_SIZE(x) (((x) & SYM_MASK_SIZE) == SYM_SIZE)
+
/* Symbol value type */
#define SYM_CONST 0x00U /* Mask bit for const values */
#define SYM_EXPR 0x10U /* Mask bit for expr values */
#define SYM_IS_EQUATE(x) (((x) & SYM_MASK_LABEL) == SYM_EQUATE)
#define SYM_IS_LABEL(x) (((x) & SYM_MASK_LABEL) == SYM_LABEL)
-/* Symbol type */
+/* Symbol type */
#define SYM_STD 0x00U /* Standard symbol */
#define SYM_CHEAP_LOCAL 0x40U /* Cheap local symbol */
#define SYM_MASK_TYPE 0x40U /* Value mask */
/* Version numbers of the debug format we understand */
#define VER_MAJOR 1U
-#define VER_MINOR 1U
+#define VER_MINOR 2U
/* Dynamic strings */
typedef struct StrBuf StrBuf;
TOK_PLUS, /* + */
TOK_EOL, /* \n */
- TOK_ABSOLUTE, /* ABSOLUTE keyword */
+ TOK_FIRST_KEYWORD,
+ TOK_ABSOLUTE = TOK_FIRST_KEYWORD, /* ABSOLUTE keyword */
TOK_ADDRSIZE, /* ADDRSIZE keyword */
TOK_COUNT, /* COUNT keyword */
TOK_EQUATE, /* EQUATE keyword */
TOK_VALUE, /* VALUE keyword */
TOK_VERSION, /* VERSION keyword */
TOK_ZEROPAGE, /* ZEROPAGE keyword */
+ TOK_LAST_KEYWORD = TOK_ZEROPAGE,
TOK_IDENT, /* To catch unknown keywords */
} Token;
struct SymInfo {
cc65_symbol_type Type; /* Type of symbol */
long Value; /* Value of symbol */
+ cc65_size Size; /* Size of symbol */
char SymName[1]; /* Name of symbol */
};
}
if (I <= J) {
/* Swap I and J */
- void* Tmp = Items[I];
+ void* Tmp = Items[I];
Items[I] = Items[J];
Items[J] = Tmp;
++I;
-static SymInfo* NewSymInfo (const StrBuf* Name, long Val, cc65_symbol_type Type)
+static SymInfo* NewSymInfo (const StrBuf* Name, long Val,
+ cc65_symbol_type Type, cc65_size Size)
/* Create a new SymInfo struct, intialize and return it */
{
/* Allocate memory */
SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name));
/* Initialize it */
- S->Value = Val;
S->Type = Type;
+ S->Value = Val;
+ S->Size = Size;
memcpy (S->SymName, SB_GetConstBuf (Name), SB_GetLen (Name) + 1);
/* Return it */
{
D->symbol_name = S->SymName;
D->symbol_type = S->Type;
+ D->symbol_size = S->Size;
D->symbol_value = S->Value;
}
{ "range", TOK_RANGE },
{ "ro", TOK_RO },
{ "rw", TOK_RW },
+ { "seg", TOK_SEGMENT },
{ "segment", TOK_SEGMENT },
{ "size", TOK_SIZE },
{ "start", TOK_START },
+static int TokenIsKeyword (Token Tok)
+/* Return true if the given token is a keyword */
+{
+ return (Tok >= TOK_FIRST_KEYWORD && Tok <= TOK_LAST_KEYWORD);
+}
+
+
+
static int TokenFollows (InputData* D, Token Tok, const char* Name)
-/* Check for a comma */
+/* Check for a specific token that follows. */
{
if (D->Tok != Tok) {
ParseError (D, CC65_ERROR, "%s expected", Name);
Token Tok;
- /* Check for an unknown keyword */
- if (D->Tok == TOK_IDENT) {
- UnknownKeyword (D);
- continue;
- }
-
/* Something we know? */
if (D->Tok != TOK_ID && D->Tok != TOK_MTIME &&
D->Tok != TOK_NAME && D->Tok != TOK_SIZE) {
+
+ /* Try smart error recovery */
+ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
+ UnknownKeyword (D);
+ continue;
+ }
+
/* Done */
break;
}
Token Tok;
- /* Check for an unknown keyword */
- if (D->Tok == TOK_IDENT) {
- UnknownKeyword (D);
- continue;
- }
-
/* Something we know? */
if (D->Tok != TOK_COUNT && D->Tok != TOK_FILE &&
D->Tok != TOK_LINE && D->Tok != TOK_RANGE &&
D->Tok != TOK_SEGMENT && D->Tok != TOK_TYPE) {
+
+ /* Try smart error recovery */
+ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
+ UnknownKeyword (D);
+ continue;
+ }
+
/* Done */
break;
}
Token Tok;
- /* Check for an unknown keyword */
- if (D->Tok == TOK_IDENT) {
- UnknownKeyword (D);
- continue;
- }
-
/* Something we know? */
if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_ID &&
D->Tok != TOK_NAME && D->Tok != TOK_OUTPUTNAME &&
D->Tok != TOK_OUTPUTOFFS && D->Tok != TOK_SIZE &&
D->Tok != TOK_START && D->Tok != TOK_TYPE) {
+
+ /* Try smart error recovery */
+ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
+ UnknownKeyword (D);
+ continue;
+ }
/* Done */
break;
}
{
cc65_symbol_type Type;
long Value;
+ cc65_size Size = 0;
StrBuf SymName = STRBUF_INITIALIZER;
SymInfo* S;
enum {
ibValue = 0x02,
ibAddrSize = 0x04,
ibType = 0x08,
+ ibSize = 0x10,
ibRequired = ibSymName | ibValue | ibAddrSize | ibType,
} InfoBits = ibNone;
Token Tok;
- /* Check for an unknown keyword */
- if (D->Tok == TOK_IDENT) {
- UnknownKeyword (D);
- continue;
- }
-
/* Something we know? */
if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_NAME &&
- D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) {
+ D->Tok != TOK_SIZE && D->Tok != TOK_TYPE &&
+ D->Tok != TOK_VALUE) {
+
+ /* Try smart error recovery */
+ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
+ UnknownKeyword (D);
+ continue;
+ }
+
/* Done */
break;
}
NextToken (D);
break;
+ case TOK_SIZE:
+ if (!IntConstFollows (D)) {
+ goto ErrorExit;
+ }
+ Size = (cc65_size) D->IVal;
+ InfoBits |= ibSize;
+ NextToken (D);
+ break;
+
case TOK_TYPE:
switch (D->Tok) {
case TOK_EQUATE:
}
/* Create the symbol info and remember it */
- S = NewSymInfo (&SymName, Value, Type);
+ S = NewSymInfo (&SymName, Value, Type, Size);
CollAppend (&D->Info->SymInfoByName, S);
CollAppend (&D->Info->SymInfoByVal, S);
ParseError (&D, CC65_ERROR,
"\"version\" keyword missing in first line - this is not "
"a valid debug info file");
- } else {
-
- /* Parse the version directive and check the version */
- ParseVersion (&D);
- if (D.MajorVersion > VER_MAJOR) {
- ParseError (&D, CC65_WARNING,
- "The format of this debug info file is newer than what we "
- "know. Will proceed but probably fail. Version found = %u, "
- "version supported = %u",
- D.MajorVersion, VER_MAJOR);
- }
- ConsumeEOL (&D);
-
- /* Parse lines */
- while (D.Tok != TOK_EOF) {
-
- switch (D.Tok) {
-
- case TOK_FILE:
- ParseFile (&D);
- break;
+ goto CloseAndExit;
+ }
+
+ /* Parse the version directive */
+ ParseVersion (&D);
+
+ /* Do several checks on the version number */
+ if (D.MajorVersion < VER_MAJOR) {
+ ParseError (
+ &D, CC65_ERROR,
+ "This is an old version of the debug info format that is no "
+ "longer supported. Version found = %u.%u, version supported "
+ "= %u.%u",
+ D.MajorVersion, D.MinorVersion, VER_MAJOR, VER_MINOR
+ );
+ goto CloseAndExit;
+ } else if (D.MajorVersion == VER_MAJOR && D.MinorVersion > VER_MINOR) {
+ ParseError (
+ &D, CC65_ERROR,
+ "This is a slightly newer version of the debug info format. "
+ "It might work, but you may get errors about unknown keywords "
+ "and similar. Version found = %u.%u, version supported = %u.%u",
+ D.MajorVersion, D.MinorVersion, VER_MAJOR, VER_MINOR
+ );
+ } else if (D.MajorVersion > VER_MAJOR) {
+ ParseError (
+ &D, CC65_WARNING,
+ "The format of this debug info file is newer than what we "
+ "know. Will proceed but probably fail. Version found = %u.%u, "
+ "version supported = %u.%u",
+ D.MajorVersion, D.MinorVersion, VER_MAJOR, VER_MINOR
+ );
+ }
+ ConsumeEOL (&D);
+
+ /* Parse lines */
+ while (D.Tok != TOK_EOF) {
+
+ switch (D.Tok) {
- case TOK_LINE:
- ParseLine (&D);
- break;
+ case TOK_FILE:
+ ParseFile (&D);
+ break;
- case TOK_SEGMENT:
- ParseSegment (&D);
- break;
+ case TOK_LINE:
+ ParseLine (&D);
+ break;
- case TOK_SYM:
- ParseSym (&D);
- break;
+ case TOK_SEGMENT:
+ ParseSegment (&D);
+ break;
- case TOK_IDENT:
- /* Output a warning, then skip the line with the unknown
- * keyword that may have been added by a later version.
- */
- ParseError (&D, CC65_WARNING,
- "Unknown keyword \"%s\" - skipping",
- SB_GetConstBuf (&D.SVal));
+ case TOK_SYM:
+ ParseSym (&D);
+ break;
- SkipLine (&D);
- break;
+ case TOK_IDENT:
+ /* Output a warning, then skip the line with the unknown
+ * keyword that may have been added by a later version.
+ */
+ ParseError (&D, CC65_WARNING,
+ "Unknown keyword \"%s\" - skipping",
+ SB_GetConstBuf (&D.SVal));
- default:
- UnexpectedToken (&D);
+ SkipLine (&D);
+ break;
- }
+ default:
+ UnexpectedToken (&D);
- /* EOL or EOF must follow */
- ConsumeEOL (&D);
}
+
+ /* EOL or EOF must follow */
+ ConsumeEOL (&D);
}
+CloseAndExit:
/* Close the file */
fclose (D.F);
/* Get a pointer to the file list */
FileInfoByName = &Info->FileInfoByName;
- /* Allocate memory for the data structure returned to the caller.
+ /* Allocate memory for the data structure returned to the caller.
* Note: To simplify things, we will allocate the maximum amount of
- * memory, we may need later. This saves us the overhead of walking
+ * memory, we may need later. This saves us the overhead of walking
* the list twice.
*/
D = new_cc65_sourceinfo (CollCount (FileInfoByName));
-/* Data types used for addresses and line numbers. Change to "unsigned long"
- * if you ever want to run the code on a 16-bit machine.
+/* Data types used for addresses, sizes and line numbers. Change to "unsigned
+ * long" if you ever want to run the code on a 16-bit machine.
*/
typedef unsigned cc65_line; /* Used to store line numbers */
-typedef unsigned cc65_addr; /* Use to store (65xx) addresses */
+typedef unsigned cc65_addr; /* Used to store (65xx) addresses */
+typedef unsigned cc65_size; /* Used to store (65xx) sizes */
/* Pointer to an opaque data structure containing information from the debug
* info file. Actually a handle to the data in the file.
struct cc65_symboldata {
const char* symbol_name; /* Name of symbol */
cc65_symbol_type symbol_type; /* Type of symbol */
+ cc65_size symbol_size; /* Size of symbol, 0 if unknown */
long symbol_value; /* Value of symbol */
};
/* */
/* */
/* */
-/* (C) 2010, Ullrich von Bassewitz */
+/* (C) 2010-2011, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
static void PrintSymbolData (const cc65_symboldata* D)
/* Print the data for one symbol */
{
- printf (" %-20s = %04lX\n", D->symbol_name, D->symbol_value);
+ printf (" %-20s = %04lX (size %u)\n",
+ D->symbol_name,
+ D->symbol_value,
+ D->symbol_size);
}
}
/* Free the debug info */
- cc65_free_dbginfo (Info);
+ cc65_free_dbginfo (Info);
return 0;
}
}
/* Output version information */
- fprintf (F, "version\tmajor=1,minor=1\n");
+ fprintf (F, "version\tmajor=1,minor=2\n");
/* Clear the debug sym table (used to detect duplicates) */
ClearDbgSymTable ();
/* Print it */
fprintf (F,
- "line\tfile=%u,line=%lu,segment=%u,range=0x%06lX-0x%06lX",
+ "line\tfile=%u,line=%lu,segment=%u,range=0x%lX-0x%lX",
LI->File->Id, GetSourceLine (LI), R->Seg->Id,
R->Offs, R->Offs + R->Size - 1);
D->Obj = O;
D->LineInfos = EmptyCollection;
D->Expr = 0;
+ D->Size = 0;
D->Name = 0;
D->Type = Type;
D->AddrSize = AddrSize;
/* Read a debug symbol from a file, insert and return it */
{
/* Read the type and address size */
- unsigned char Type = ReadVar (F);
+ unsigned Type = ReadVar (F);
unsigned char AddrSize = Read8 (F);
/* Create a new debug symbol */
D->Expr = LiteralExpr (Read32 (F), O);
}
+ /* Read the size */
+ if (SYM_HAS_SIZE (D->Type)) {
+ D->Size = ReadVar (F);
+ }
+
/* Last is the list of line infos for this symbol */
ReadLineInfoList (F, O, &D->LineInfos);
/* Emit the debug file line */
fprintf (F,
- "sym\tname=\"%s\",value=0x%08lX,addrsize=%s,type=%s\n",
+ "sym\tname=\"%s\",value=0x%lX,addrsize=%s,type=%s",
GetString (D->Name),
Val,
AddrSizeToStr (D->AddrSize),
SYM_IS_LABEL (D->Type)? "label" : "equate");
+ if (D->Size != 0) {
+ fprintf (F, ",size=%lu", D->Size);
+ }
+ fputc ('\n', F);
/* Insert the symbol into the table */
InsertDbgSym (D, Val);
ObjData* Obj; /* Object file that exports the name */
Collection LineInfos; /* Line infos of definition */
ExprNode* Expr; /* Expression (0 if not def'd) */
+ unsigned long Size; /* Symbol size if any */
unsigned Name; /* Name */
unsigned char Type; /* Type of symbol */
unsigned char AddrSize; /* Address size of symbol */
E->ImpCount = 0;
E->ImpList = 0;
E->Expr = 0;
+ E->Size = 0;
E->LineInfos = EmptyCollection;
E->Type = Type;
E->AddrSize = AddrSize;
E->Expr = LiteralExpr (Read32 (F), O);
}
+ /* Read the size */
+ if (SYM_HAS_SIZE (Type)) {
+ E->Size = ReadVar (F);
+ }
+
/* Last is the file position where the definition was done */
ReadLineInfoList (F, O, &E->LineInfos);
Imp = E->ImpList;
while (Imp) {
Imp->Exp = E;
- Imp = Imp->Next;
+ Imp = Imp->Next;
}
} else {
/* Duplicate entry, ignore it */
}
-
+
static int CmpExpName (const void* K1, const void* K2)
/* Compare function for qsort */
{
unsigned ImpCount; /* How many imports for this symbol? */
Import* ImpList; /* List of imports for this symbol */
ExprNode* Expr; /* Expression (0 if not def'd) */
+ unsigned long Size; /* Size of the symbol if any */
Collection LineInfos; /* Line info of definition */
unsigned char Type; /* Type of export */
unsigned char AddrSize; /* Address size of export */
case SYM_EXPR: strcat (TypeDesc, ",SYM_EXPR"); break;
}
+ /* Size available? */
+ if (SYM_HAS_SIZE (Flags)) {
+ strcat (TypeDesc, ",SYM_SIZE");
+ }
+
+
/* Constructor/destructor declarations */
T = TypeDesc + strlen (TypeDesc);
Count = SYM_GET_CONDES_COUNT (Flags);
if (Count > 0 && ConDes) {
- T += sprintf (T, ",SYM_CONDES=");
- for (I = 0; I < Count; ++I) {
- unsigned Type = CD_GET_TYPE (ConDes[I]);
- unsigned Prio = CD_GET_PRIO (ConDes[I]);
- if (I > 0) {
- *T++ = ',';
- }
+ T += sprintf (T, ",SYM_CONDES=");
+ for (I = 0; I < Count; ++I) {
+ unsigned Type = CD_GET_TYPE (ConDes[I]);
+ unsigned Prio = CD_GET_PRIO (ConDes[I]);
+ if (I > 0) {
+ *T++ = ',';
+ }
T += sprintf (T, "[%u,%u]", Type, Prio);
- }
+ }
}
/* Return the result */
for (I = 0; I < Count; ++I) {
unsigned long Value = 0;
- int HaveValue;
- unsigned char ConDes [CD_TYPE_COUNT];
+ unsigned long Size = 0;
+ unsigned char ConDes[CD_TYPE_COUNT];
const char* Name;
unsigned Len;
ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));
Name = GetString (&StrPool, ReadVar (F));
Len = strlen (Name);
- if (SYM_IS_EXPR (Type)) {
- SkipExpr (F);
- HaveValue = 0;
- } else {
+ if (SYM_IS_CONST (Type)) {
Value = Read32 (F);
- HaveValue = 1;
+ } else {
+ SkipExpr (F);
}
+ if (SYM_HAS_SIZE (Type)) {
+ Size = ReadVar (F);
+ }
/* Skip the line infos */
SkipLineInfoList (F);
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
AddrSizeToStr (AddrSize));
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
- if (HaveValue) {
- printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
+ if (SYM_IS_CONST (Type)) {
+ printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
+ }
+ if (SYM_HAS_SIZE (Type)) {
+ printf (" Size:%16s0x%04lX (%lu)\n", "", Size, Size);
}
}
/* Read and print all debug symbols */
for (I = 0; I < Count; ++I) {
- unsigned long Value = 0;
- int HaveValue;
+ unsigned long Value = 0;
+ unsigned long Size = 0;
/* Read the data for one symbol */
unsigned Type = ReadVar (F);
unsigned char AddrSize = Read8 (F);
const char* Name = GetString (&StrPool, ReadVar (F));
unsigned Len = strlen (Name);
- if (SYM_IS_EXPR (Type)) {
- SkipExpr (F);
- HaveValue = 0;
- } else {
+ if (SYM_IS_CONST (Type)) {
Value = Read32 (F);
- HaveValue = 1;
+ } else {
+ SkipExpr (F);
}
+ if (SYM_HAS_SIZE (Type)) {
+ Size = ReadVar (F);
+ }
/* Skip the line infos */
SkipLineInfoList (F);
printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
AddrSizeToStr (AddrSize));
printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
- if (HaveValue) {
+ if (SYM_IS_CONST (Type)) {
printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
}
+ if (SYM_HAS_SIZE (Type)) {
+ printf (" Size:%16s0x%04lX (%lu)\n", "", Size, Size);
+ }
}
/* Destroy the string pool */