mirror of
https://github.com/cc65/cc65.git
synced 2025-01-14 00:32:08 +00:00
Handle imports correctly.
git-svn-id: svn://svn.cc65.org/cc65/trunk@5187 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
3996725f44
commit
7d7667f782
@ -129,9 +129,11 @@ typedef enum {
|
|||||||
TOK_COUNT, /* COUNT keyword */
|
TOK_COUNT, /* COUNT keyword */
|
||||||
TOK_ENUM, /* ENUM keyword */
|
TOK_ENUM, /* ENUM keyword */
|
||||||
TOK_EQUATE, /* EQUATE keyword */
|
TOK_EQUATE, /* EQUATE keyword */
|
||||||
|
TOK_EXPORT, /* EXPORT keyword */
|
||||||
TOK_FILE, /* FILE keyword */
|
TOK_FILE, /* FILE keyword */
|
||||||
TOK_GLOBAL, /* GLOBAL keyword */
|
TOK_GLOBAL, /* GLOBAL keyword */
|
||||||
TOK_ID, /* ID keyword */
|
TOK_ID, /* ID keyword */
|
||||||
|
TOK_IMPORT, /* IMPORT keyword */
|
||||||
TOK_INFO, /* INFO keyword */
|
TOK_INFO, /* INFO keyword */
|
||||||
TOK_LABEL, /* LABEL keyword */
|
TOK_LABEL, /* LABEL keyword */
|
||||||
TOK_LIBRARY, /* LIBRARY keyword */
|
TOK_LIBRARY, /* LIBRARY keyword */
|
||||||
@ -322,6 +324,10 @@ struct SymInfo {
|
|||||||
cc65_symbol_type Type; /* Type of symbol */
|
cc65_symbol_type Type; /* Type of symbol */
|
||||||
long Value; /* Value of symbol */
|
long Value; /* Value of symbol */
|
||||||
cc65_size Size; /* Size of symbol */
|
cc65_size Size; /* Size of symbol */
|
||||||
|
union {
|
||||||
|
unsigned Id; /* Id of export if any */
|
||||||
|
SymInfo* Info; /* Pointer to export if any */
|
||||||
|
} Exp;
|
||||||
union {
|
union {
|
||||||
unsigned Id; /* Id of segment if any */
|
unsigned Id; /* Id of segment if any */
|
||||||
SegInfo* Info; /* Pointer to segment if any */
|
SegInfo* Info; /* Pointer to segment if any */
|
||||||
@ -1562,13 +1568,28 @@ static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count)
|
|||||||
static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
|
static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
|
||||||
/* Copy data from a SymInfo struct to a cc65_symboldata struct */
|
/* Copy data from a SymInfo struct to a cc65_symboldata struct */
|
||||||
{
|
{
|
||||||
|
SegInfo* Seg;
|
||||||
|
|
||||||
D->symbol_id = S->Id;
|
D->symbol_id = S->Id;
|
||||||
D->symbol_name = S->Name;
|
D->symbol_name = S->Name;
|
||||||
D->symbol_type = S->Type;
|
D->symbol_type = S->Type;
|
||||||
D->symbol_size = S->Size;
|
D->symbol_size = S->Size;
|
||||||
|
|
||||||
|
/* If this is an import, it doesn't have a value or segment. Use the data
|
||||||
|
* from the matching export instead.
|
||||||
|
*/
|
||||||
|
if (S->Exp.Info) {
|
||||||
|
/* This is an import, because it has a matching export */
|
||||||
|
D->export_id = S->Exp.Info->Id;
|
||||||
|
D->symbol_value = S->Exp.Info->Value;
|
||||||
|
Seg = S->Exp.Info->Seg.Info;
|
||||||
|
} else {
|
||||||
|
D->export_id = CC65_INV_ID;
|
||||||
D->symbol_value = S->Value;
|
D->symbol_value = S->Value;
|
||||||
if (S->Seg.Info) {
|
Seg = S->Seg.Info;
|
||||||
D->segment_id = S->Seg.Info->Id;
|
}
|
||||||
|
if (Seg) {
|
||||||
|
D->segment_id = Seg->Id;
|
||||||
} else {
|
} else {
|
||||||
D->segment_id = CC65_INV_ID;
|
D->segment_id = CC65_INV_ID;
|
||||||
}
|
}
|
||||||
@ -2033,9 +2054,11 @@ static void NextToken (InputData* D)
|
|||||||
{ "count", TOK_COUNT },
|
{ "count", TOK_COUNT },
|
||||||
{ "enum", TOK_ENUM },
|
{ "enum", TOK_ENUM },
|
||||||
{ "equ", TOK_EQUATE },
|
{ "equ", TOK_EQUATE },
|
||||||
|
{ "exp", TOK_EXPORT },
|
||||||
{ "file", TOK_FILE },
|
{ "file", TOK_FILE },
|
||||||
{ "global", TOK_GLOBAL },
|
{ "global", TOK_GLOBAL },
|
||||||
{ "id", TOK_ID },
|
{ "id", TOK_ID },
|
||||||
|
{ "imp", TOK_IMPORT },
|
||||||
{ "info", TOK_INFO },
|
{ "info", TOK_INFO },
|
||||||
{ "lab", TOK_LABEL },
|
{ "lab", TOK_LABEL },
|
||||||
{ "lib", TOK_LIBRARY },
|
{ "lib", TOK_LIBRARY },
|
||||||
@ -3428,6 +3451,7 @@ static void ParseSym (InputData* D)
|
|||||||
/* Most of the following variables are initialized with a value that is
|
/* Most of the following variables are initialized with a value that is
|
||||||
* overwritten later. This is just to avoid compiler warnings.
|
* overwritten later. This is just to avoid compiler warnings.
|
||||||
*/
|
*/
|
||||||
|
unsigned ExportId = CC65_INV_ID;
|
||||||
unsigned FileId = CC65_INV_ID;
|
unsigned FileId = CC65_INV_ID;
|
||||||
unsigned Id = CC65_INV_ID;
|
unsigned Id = CC65_INV_ID;
|
||||||
StrBuf Name = STRBUF_INITIALIZER;
|
StrBuf Name = STRBUF_INITIALIZER;
|
||||||
@ -3443,17 +3467,18 @@ static void ParseSym (InputData* D)
|
|||||||
ibNone = 0x000,
|
ibNone = 0x000,
|
||||||
|
|
||||||
ibAddrSize = 0x001,
|
ibAddrSize = 0x001,
|
||||||
ibFileId = 0x002,
|
ibExportId = 0x002,
|
||||||
ibId = 0x004,
|
ibFileId = 0x004,
|
||||||
ibParentId = 0x008,
|
ibId = 0x008,
|
||||||
ibScopeId = 0x010,
|
ibParentId = 0x010,
|
||||||
ibSegId = 0x020,
|
ibScopeId = 0x020,
|
||||||
ibSize = 0x040,
|
ibSegId = 0x040,
|
||||||
ibName = 0x080,
|
ibSize = 0x080,
|
||||||
ibType = 0x100,
|
ibName = 0x100,
|
||||||
ibValue = 0x200,
|
ibType = 0x200,
|
||||||
|
ibValue = 0x400,
|
||||||
|
|
||||||
ibRequired = ibAddrSize | ibId | ibName | ibType | ibValue,
|
ibRequired = ibAddrSize | ibId | ibName,
|
||||||
} InfoBits = ibNone;
|
} InfoBits = ibNone;
|
||||||
|
|
||||||
/* Skip the SYM token */
|
/* Skip the SYM token */
|
||||||
@ -3465,11 +3490,12 @@ static void ParseSym (InputData* D)
|
|||||||
Token Tok;
|
Token Tok;
|
||||||
|
|
||||||
/* Something we know? */
|
/* Something we know? */
|
||||||
if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_FILE &&
|
if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_EXPORT &&
|
||||||
D->Tok != TOK_ID && D->Tok != TOK_NAME &&
|
D->Tok != TOK_FILE && D->Tok != TOK_ID &&
|
||||||
D->Tok != TOK_PARENT && D->Tok != TOK_SCOPE &&
|
D->Tok != TOK_NAME && D->Tok != TOK_PARENT &&
|
||||||
D->Tok != TOK_SEGMENT && D->Tok != TOK_SIZE &&
|
D->Tok != TOK_SCOPE && D->Tok != TOK_SEGMENT &&
|
||||||
D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) {
|
D->Tok != TOK_SIZE && D->Tok != TOK_TYPE &&
|
||||||
|
D->Tok != TOK_VALUE) {
|
||||||
|
|
||||||
/* Try smart error recovery */
|
/* Try smart error recovery */
|
||||||
if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
|
if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
|
||||||
@ -3496,6 +3522,15 @@ static void ParseSym (InputData* D)
|
|||||||
InfoBits |= ibAddrSize;
|
InfoBits |= ibAddrSize;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOK_EXPORT:
|
||||||
|
if (!IntConstFollows (D)) {
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
ExportId = D->IVal;
|
||||||
|
InfoBits |= ibExportId;
|
||||||
|
NextToken (D);
|
||||||
|
break;
|
||||||
|
|
||||||
case TOK_FILE:
|
case TOK_FILE:
|
||||||
if (!IntConstFollows (D)) {
|
if (!IntConstFollows (D)) {
|
||||||
goto ErrorExit;
|
goto ErrorExit;
|
||||||
@ -3564,7 +3599,6 @@ static void ParseSym (InputData* D)
|
|||||||
switch (D->Tok) {
|
switch (D->Tok) {
|
||||||
case TOK_EQUATE: Type = CC65_SYM_EQUATE; break;
|
case TOK_EQUATE: Type = CC65_SYM_EQUATE; break;
|
||||||
case TOK_LABEL: Type = CC65_SYM_LABEL; break;
|
case TOK_LABEL: Type = CC65_SYM_LABEL; break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ParseError (D, CC65_ERROR,
|
ParseError (D, CC65_ERROR,
|
||||||
"Unknown value for attribute \"type\"");
|
"Unknown value for attribute \"type\"");
|
||||||
@ -3622,6 +3656,7 @@ static void ParseSym (InputData* D)
|
|||||||
S->Type = Type;
|
S->Type = Type;
|
||||||
S->Value = Value;
|
S->Value = Value;
|
||||||
S->Size = Size;
|
S->Size = Size;
|
||||||
|
S->Exp.Id = ExportId;
|
||||||
S->Seg.Id = SegId;
|
S->Seg.Id = SegId;
|
||||||
S->Scope.Id = ScopeId;
|
S->Scope.Id = ScopeId;
|
||||||
S->Parent.Id = ParentId;
|
S->Parent.Id = ParentId;
|
||||||
@ -4249,6 +4284,19 @@ static void ProcessSymInfo (InputData* D)
|
|||||||
/* Get the symbol info */
|
/* Get the symbol info */
|
||||||
SymInfo* S = CollAt (&D->Info->SymInfoById, I);
|
SymInfo* S = CollAt (&D->Info->SymInfoById, I);
|
||||||
|
|
||||||
|
/* Resolve export */
|
||||||
|
if (S->Exp.Id == CC65_INV_ID) {
|
||||||
|
S->Exp.Info = 0;
|
||||||
|
} else if (S->Exp.Id >= CollCount (&D->Info->SymInfoById)) {
|
||||||
|
ParseError (D,
|
||||||
|
CC65_ERROR,
|
||||||
|
"Invalid export id %u for symbol with id %u",
|
||||||
|
S->Exp.Id, S->Id);
|
||||||
|
S->Exp.Info = 0;
|
||||||
|
} else {
|
||||||
|
S->Exp.Info = CollAt (&D->Info->SymInfoById, S->Exp.Id);
|
||||||
|
}
|
||||||
|
|
||||||
/* Resolve segment */
|
/* Resolve segment */
|
||||||
if (S->Seg.Id == CC65_INV_ID) {
|
if (S->Seg.Id == CC65_INV_ID) {
|
||||||
S->Seg.Info = 0;
|
S->Seg.Info = 0;
|
||||||
|
@ -380,6 +380,16 @@ typedef enum {
|
|||||||
CC65_SYM_LABEL, /* Some sort of address */
|
CC65_SYM_LABEL, /* Some sort of address */
|
||||||
} cc65_symbol_type;
|
} cc65_symbol_type;
|
||||||
|
|
||||||
|
/* Notes:
|
||||||
|
* - If the symbol is segment relative, the segment id gives segment
|
||||||
|
* information, otherwise it contains CC65_INV_ID.
|
||||||
|
* - If export_id is valid (not CC65_INV_ID), the symbol is an import and
|
||||||
|
* export_id allows to retrieve the corresponding export. The fields
|
||||||
|
* symbol_value and segment_id are taken from the export, since imports
|
||||||
|
* have no value or segments by itself. symbol_type and symbol_size are
|
||||||
|
* more or less unusable because they don't have a meaning for imports.
|
||||||
|
* - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID.
|
||||||
|
*/
|
||||||
typedef struct cc65_symboldata cc65_symboldata;
|
typedef struct cc65_symboldata cc65_symboldata;
|
||||||
struct cc65_symboldata {
|
struct cc65_symboldata {
|
||||||
unsigned symbol_id; /* Id of symbol */
|
unsigned symbol_id; /* Id of symbol */
|
||||||
@ -387,10 +397,8 @@ struct cc65_symboldata {
|
|||||||
cc65_symbol_type symbol_type; /* Type of symbol */
|
cc65_symbol_type symbol_type; /* Type of symbol */
|
||||||
cc65_size symbol_size; /* Size of symbol, 0 if unknown */
|
cc65_size symbol_size; /* Size of symbol, 0 if unknown */
|
||||||
long symbol_value; /* Value of symbol */
|
long symbol_value; /* Value of symbol */
|
||||||
unsigned segment_id; /* If the symbol is segment relative,
|
unsigned export_id; /* For imports: Matching export */
|
||||||
* this contains the id of segment,
|
unsigned segment_id; /* Id of segment if any */
|
||||||
* otherwise CC65_INV_ID
|
|
||||||
*/
|
|
||||||
unsigned scope_id; /* The scope this symbol is in */
|
unsigned scope_id; /* The scope this symbol is in */
|
||||||
unsigned parent_id; /* Parent symbol for cheap locals */
|
unsigned parent_id; /* Parent symbol for cheap locals */
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user