]> git.sur5r.net Git - cc65/commitdiff
Handle imports correctly.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 16 Aug 2011 14:25:18 +0000 (14:25 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 16 Aug 2011 14:25:18 +0000 (14:25 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@5187 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/dbginfo/dbginfo.c
src/dbginfo/dbginfo.h

index be516f1b6eabad96166c8d748e2d54f8a09424b7..56dbe59904c4264c6af21aee619e290e77153398 100644 (file)
@@ -129,9 +129,11 @@ typedef enum {
     TOK_COUNT,                          /* COUNT keyword */
     TOK_ENUM,                           /* ENUM keyword */
     TOK_EQUATE,                         /* EQUATE keyword */
+    TOK_EXPORT,                         /* EXPORT keyword */
     TOK_FILE,                           /* FILE keyword */
     TOK_GLOBAL,                         /* GLOBAL keyword */
     TOK_ID,                             /* ID keyword */
+    TOK_IMPORT,                         /* IMPORT keyword */
     TOK_INFO,                           /* INFO keyword */
     TOK_LABEL,                          /* LABEL keyword */
     TOK_LIBRARY,                        /* LIBRARY keyword */
@@ -322,6 +324,10 @@ struct SymInfo {
     cc65_symbol_type    Type;           /* Type of symbol */
     long                Value;          /* Value 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 {
         unsigned        Id;             /* Id of segment if any */
         SegInfo*        Info;           /* Pointer to segment if any */
@@ -1158,7 +1164,7 @@ static LineInfo* NewLineInfo (void)
 
 static void FreeLineInfo (LineInfo* L)
 /* Free a LineInfo struct */
-{           
+{
     CollDone (&L->SpanInfoList);
     xfree (L);
 }
@@ -1562,13 +1568,28 @@ static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count)
 static void CopySymInfo (cc65_symboldata* D, const SymInfo* S)
 /* Copy data from a SymInfo struct to a cc65_symboldata struct */
 {
+    SegInfo* Seg;
+
     D->symbol_id        = S->Id;
     D->symbol_name      = S->Name;
     D->symbol_type      = S->Type;
     D->symbol_size      = S->Size;
-    D->symbol_value     = S->Value;
-    if (S->Seg.Info) {
-        D->segment_id   = S->Seg.Info->Id;
+
+    /* 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;
+        Seg             = S->Seg.Info;
+    }
+    if (Seg) {
+        D->segment_id   = Seg->Id;
     } else {
         D->segment_id   = CC65_INV_ID;
     }
@@ -2033,9 +2054,11 @@ static void NextToken (InputData* D)
         { "count",      TOK_COUNT       },
         { "enum",       TOK_ENUM        },
         { "equ",        TOK_EQUATE      },
+        { "exp",        TOK_EXPORT      },
         { "file",       TOK_FILE        },
         { "global",     TOK_GLOBAL      },
         { "id",         TOK_ID          },
+        { "imp",        TOK_IMPORT      },
         { "info",       TOK_INFO        },
         { "lab",        TOK_LABEL       },
         { "lib",        TOK_LIBRARY     },
@@ -3428,6 +3451,7 @@ static void ParseSym (InputData* D)
     /* Most of the following variables are initialized with a value that is
      * overwritten later. This is just to avoid compiler warnings.
      */
+    unsigned            ExportId = CC65_INV_ID;
     unsigned            FileId = CC65_INV_ID;
     unsigned            Id = CC65_INV_ID;
     StrBuf              Name = STRBUF_INITIALIZER;
@@ -3435,7 +3459,7 @@ static void ParseSym (InputData* D)
     unsigned            ScopeId = CC65_INV_ID;
     unsigned            SegId = CC65_INV_ID;
     cc65_size           Size = 0;
-    cc65_symbol_type    Type = CC65_SYM_EQUATE;
+    cc65_symbol_type    Type = CC65_SYM_EQUATE;     
     long                Value = 0;
 
     SymInfo*            S;
@@ -3443,17 +3467,18 @@ static void ParseSym (InputData* D)
         ibNone          = 0x000,
 
         ibAddrSize      = 0x001,
-        ibFileId        = 0x002,
-        ibId            = 0x004,
-        ibParentId      = 0x008,
-        ibScopeId       = 0x010,
-        ibSegId         = 0x020,
-        ibSize          = 0x040,
-        ibName          = 0x080,
-        ibType          = 0x100,
-        ibValue         = 0x200,
-
-        ibRequired      = ibAddrSize | ibId | ibName | ibType | ibValue,
+        ibExportId      = 0x002,
+        ibFileId        = 0x004,
+        ibId            = 0x008,
+        ibParentId      = 0x010,
+        ibScopeId       = 0x020,
+        ibSegId         = 0x040,
+        ibSize          = 0x080,
+        ibName          = 0x100,
+        ibType          = 0x200,
+        ibValue         = 0x400,
+
+        ibRequired      = ibAddrSize | ibId | ibName,
     } InfoBits = ibNone;
 
     /* Skip the SYM token */
@@ -3465,11 +3490,12 @@ static void ParseSym (InputData* D)
         Token Tok;
 
         /* Something we know? */
-        if (D->Tok != TOK_ADDRSIZE      && D->Tok != TOK_FILE   &&
-            D->Tok != TOK_ID            && D->Tok != TOK_NAME   &&
-            D->Tok != TOK_PARENT        && D->Tok != TOK_SCOPE  &&
-            D->Tok != TOK_SEGMENT       && D->Tok != TOK_SIZE   &&
-            D->Tok != TOK_TYPE          && D->Tok != TOK_VALUE) {
+        if (D->Tok != TOK_ADDRSIZE      && D->Tok != TOK_EXPORT         &&
+            D->Tok != TOK_FILE          && D->Tok != TOK_ID             &&
+            D->Tok != TOK_NAME          && D->Tok != TOK_PARENT         &&
+            D->Tok != TOK_SCOPE         && D->Tok != TOK_SEGMENT        &&
+            D->Tok != TOK_SIZE          && D->Tok != TOK_TYPE           &&
+            D->Tok != TOK_VALUE) {
 
             /* Try smart error recovery */
             if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) {
@@ -3496,6 +3522,15 @@ static void ParseSym (InputData* D)
                 InfoBits |= ibAddrSize;
                 break;
 
+            case TOK_EXPORT:
+                if (!IntConstFollows (D)) {
+                    goto ErrorExit;
+                }
+                ExportId = D->IVal;
+                InfoBits |= ibExportId;
+                NextToken (D);
+                break;
+
             case TOK_FILE:
                 if (!IntConstFollows (D)) {
                     goto ErrorExit;
@@ -3564,7 +3599,6 @@ static void ParseSym (InputData* D)
                 switch (D->Tok) {
                     case TOK_EQUATE:    Type = CC65_SYM_EQUATE;         break;
                     case TOK_LABEL:     Type = CC65_SYM_LABEL;          break;
-
                     default:
                         ParseError (D, CC65_ERROR,
                                     "Unknown value for attribute \"type\"");
@@ -3622,6 +3656,7 @@ static void ParseSym (InputData* D)
     S->Type       = Type;
     S->Value      = Value;
     S->Size       = Size;
+    S->Exp.Id     = ExportId;
     S->Seg.Id     = SegId;
     S->Scope.Id   = ScopeId;
     S->Parent.Id  = ParentId;
@@ -4249,6 +4284,19 @@ static void ProcessSymInfo (InputData* D)
         /* Get the symbol info */
         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 */
         if (S->Seg.Id == CC65_INV_ID) {
             S->Seg.Info = 0;
index 617a769e91fa28371339e042209651c718247420..fe141538578138cee9fcebac5e7447c26c5d729b 100644 (file)
@@ -380,6 +380,16 @@ typedef enum {
     CC65_SYM_LABEL,                     /* Some sort of address */
 } 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;
 struct cc65_symboldata {
     unsigned            symbol_id;      /* Id of symbol */
@@ -387,10 +397,8 @@ struct cc65_symboldata {
     cc65_symbol_type    symbol_type;    /* Type of symbol */
     cc65_size           symbol_size;    /* Size of symbol, 0 if unknown */
     long                symbol_value;   /* Value of symbol */
-    unsigned            segment_id;     /* If the symbol is segment relative,
-                                         * this contains the id of segment,
-                                         * otherwise CC65_INV_ID
-                                         */
+    unsigned            export_id;      /* For imports: Matching export */
+    unsigned            segment_id;     /* Id of segment if any */
     unsigned            scope_id;       /* The scope this symbol is in */
     unsigned            parent_id;      /* Parent symbol for cheap locals */
 };