]> Shamusworld >> Repos - rmac/blobdiff - symbol.c
Version bump for last commit. :-)
[rmac] / symbol.c
index b89cd8091587571de30190d93d932a025fe6ce36..c9c34a4f6c729f34bedb94cc9ecf8204befe2a19 100644 (file)
--- a/symbol.c
+++ b/symbol.c
@@ -1,12 +1,13 @@
 //
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// RMAC - Renamed Macro Assembler for all Atari computers
 // SYMBOL.C - Symbol Handling
-// Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2022 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
 // Source utilised with the kind permission of Landon Dyer
 //
 
 #include "symbol.h"
+#include "dsp56k.h"
 #include "error.h"
 #include "listing.h"
 #include "object.h"
@@ -35,6 +36,8 @@ static uint8_t tdb_text[8] = {
    'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
 };
 
+// Internal function prototypes
+static uint16_t WriteLODSection(int, uint16_t);
 
 //
 // Initialize symbol table
@@ -52,11 +55,10 @@ void InitSymbolTable(void)
        currentUID = 0;
 }
 
-
 //
 // Hash the ASCII name and enviroment number
 //
-int HashSymbol(uint8_t * name, int envno)
+int HashSymbol(const uint8_t * name, int envno)
 {
        int sum = envno, k = 0;
 
@@ -71,11 +73,10 @@ int HashSymbol(uint8_t * name, int envno)
        return sum & (NBUCKETS - 1);
 }
 
-
 //
 // Make a new symbol of type 'type' in enviroment 'envno'
 //
-SYM * NewSymbol(uint8_t * name, int type, int envno)
+SYM * NewSymbol(const uint8_t * name, int type, int envno)
 {
        // Allocate the symbol
        SYM * symbol = malloc(sizeof(SYM));
@@ -87,7 +88,7 @@ SYM * NewSymbol(uint8_t * name, int type, int envno)
        }
 
        // Fill-in the symbol
-       symbol->sname  = strdup(name);
+       symbol->sname  = name ? strdup(name) : NULL;
        symbol->stype  = (uint8_t)type;
        symbol->senv   = (uint16_t)envno;
        // We don't set this as DEFINED, as it could be a forward reference!
@@ -98,11 +99,22 @@ SYM * NewSymbol(uint8_t * name, int type, int envno)
        symbol->svalue = 0;
        symbol->sorder = NULL;
        symbol->uid    = currentUID++;
+       // We don't set st_type, st_desc, or st_other here because they are only
+       // used by stabs debug symbols, which are always initialized by
+       // NewDebugSymbol(), which always sets these fields. Hence, initializing
+       // them here would be redundant.
 
-       // Install symbol in the symbol table
-       int hash = HashSymbol(name, envno);
-       symbol->snext = symbolTable[hash];
-       symbolTable[hash] = symbol;
+       // Record filename the symbol is defined (Used by macro error reporting and some debug symbols)
+       symbol->cfileno = cfileno;
+
+       // Don't hash debug symbols: they are never looked up and may have no name.
+       if (type != DBGSYM)
+       {
+               // Install symbol in the symbol table
+               int hash = HashSymbol(name, envno);
+               symbol->snext = symbolTable[hash];
+               symbolTable[hash] = symbol;
+       }
 
        // Append symbol to the symbol-order list
        if (sorder == NULL)
@@ -114,7 +126,6 @@ SYM * NewSymbol(uint8_t * name, int type, int envno)
        return symbol;
 }
 
-
 //
 // Look up the symbol name by its UID and return the pointer to the name.
 // If it's not found, return NULL.
@@ -139,7 +150,6 @@ uint8_t * GetSymbolNameByUID(uint32_t uid)
        return NULL;
 }
 
-
 //
 // Lookup the symbol 'name', of the specified type, with the specified
 // enviroment level
@@ -164,7 +174,6 @@ SYM * lookup(uint8_t * name, int type, int envno)
        return symbol;
 }
 
-
 //
 // Put symbol on "order-of-declaration" list of symbols
 //
@@ -188,7 +197,6 @@ void AddToSymbolDeclarationList(SYM * symbol)
        sdecltail = symbol;
 }
 
-
 //
 // Make all referenced, undefined symbols global
 //
@@ -208,7 +216,6 @@ void ForceUndefinedSymbolsGlobal(void)
        }
 }
 
-
 //
 // Assign numbers to symbols that are to be exported or imported. The symbol
 // number is put in 'senv'. Returns the number of symbols that will be in the
@@ -219,7 +226,7 @@ void ForceUndefinedSymbolsGlobal(void)
 //       count of the # of symbols in the symbol table, and the second is to
 //       actually create it.
 //
-uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)())
+uint32_t AssignSymbolNos(uint8_t * buf, uint8_t *(* construct)())
 {
        uint16_t scount = 0;
 
@@ -236,10 +243,28 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)())
        // them. We also pick which symbols should be global or not here.
        for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
        {
+               // Always export debug symbols. Don't force them global.
+               if (DBGSYM == sy->stype) {
+                       sy->senv = scount++;
+
+                       if (buf != NULL)
+                               buf = construct(buf, sy, 0);
+                       continue;
+               }
+
+               // Skip non-labels.
+               if (sy->stype != LABEL)
+                       continue;
+
+               // Nuke equated register/CC symbols from orbit:
+               if (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC))
+                       continue;
+
                // Export or import external references, and export COMMON blocks.
-               if ((sy->stype == LABEL)
-                       && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
-                       || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
+               // N.B.: This says to mark the symbol as global if either 1) the symbol
+               //       is global AND the symbol is defined OR referenced, or 2) this
+               //       symbol is a common symbol.
+               if (((sy->sattr & GLOBAL) && (sy->sattr & (DEFINED | REFERENCED)))
                        || (sy->sattr & COMMON))
                {
                        sy->senv = scount++;
@@ -249,9 +274,11 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)())
                }
                // Export vanilla labels (but don't make them global). An exception is
                // made for equates, which are not exported unless they are referenced.
-               else if (sy->stype == LABEL && lsym_flag
-                       && (sy->sattr & (DEFINED | REFERENCED)) != 0
-                       && (!as68_flag || *sy->sname != 'L'))
+               // ^^^ The above just might be bullshit. ^^^
+               // N.B.: This says if the symbol is either defined OR referenced (but
+               //       because of the above we know it *won't* be GLOBAL).  And
+               //       lsym_flag is always set true in Process() in rmac.c.
+               else if (lsym_flag && (sy->sattr & (DEFINED | REFERENCED)))
                {
                        sy->senv = scount++;
 
@@ -260,72 +287,37 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)())
                }
        }
 
-       // For ELF object mode run through all symbols in reference order
-       // and export all global-referenced labels. Not sure if this is
-       // required but it's here nonetheless
-/* why?? when you have sy_assign_ELF ???
-       if (obj_format == ELF)
-       {
-               for(sy=sdecl; sy!=NULL; sy=sy->sorder)
-               {
-                       if ((sy->sattr == (GLOBAL | REFERENCED)) && (buf != NULL))
-                       {
-                               buf = (*construct)(buf, sy, 0);
-                               scount++;
-                       }
-               }
-       }*/
-
        return scount;
 }
 
-
 //
-// Custom version of sy_assign for ELF .o files.
+// Custom version of AssignSymbolNos for ELF .o files.
 // The order that the symbols should be dumped is different.
 // (globals must be explicitly at the end of the table)
 //
-// N.B.: It should be possible to merge this with sy_assign, as there's nothing
-//       really ELF specific in here, other than the "globals go at the end of
-//       the queue" thing, which doesn't break the others. :-P
-uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)())
+// N.B.: It should be possible to merge this with AssignSymbolNos, as there's
+//       nothing really ELF specific in here, other than the "globals go at the
+//       end of the queue" thing, which doesn't break the others. :-P
+uint32_t AssignSymbolNosELF(uint8_t * buf, uint8_t *(* construct)())
 {
        uint16_t scount = 0;
 
-//     if (construct == (uint8_t *(*)())constr_elfsymtab)
-//     if (buf == NULL)
-       {
-               // Append all symbols not appearing on the .sdecl list to the end of
-               // the .sdecl list
-               for(SYM * sy=sorder; sy!=NULL; sy=sy->sorder)
-                       AddToSymbolDeclarationList(sy);
-       }
+       // Append all symbols not appearing on the .sdecl list to the end of
+       // the .sdecl list
+       for(SYM * sy=sorder; sy!=NULL; sy=sy->sorder)
+               AddToSymbolDeclarationList(sy);
 
        // Run through all symbols (now on the .sdecl list) and assign numbers to
        // them. We also pick which symbols should be global or not here.
        for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
        {
-               // Export or import external references, and export COMMON blocks.
-               //if ((sy->stype == LABEL)
-               //      && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
-               //      || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
-               //      || (sy->sattr & COMMON))
-               //{
-               //      sy->senv = (WORD)scount++;
-        //
-               //      if (buf != NULL)
-               //              buf = (*construct)(buf, sy, 1);
-               //}
                // Export vanilla labels (but don't make them global). An exception is
                // made for equates, which are not exported unless they are referenced.
                if (sy->stype == LABEL && lsym_flag
                        && (sy->sattr & (DEFINED | REFERENCED)) != 0
                        && (*sy->sname != '.')
-                       && (sy->sattr & GLOBAL) == 0)
-               //if (sy->stype == 0)
-               //      if (lsym_flag)
-               //              if ((sy->sattr & (DEFINED | REFERENCED)) != 0)
-               //                      if ((!as68_flag || *sy->sname != 'L'))
+                       && (sy->sattr & GLOBAL) == 0
+                       && (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) == 0)
                {
                        sy->senv = scount++;
 
@@ -340,10 +332,10 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)())
        // and export all global-referenced labels. Not sure if this is
        // required but it's here nonetheless
 
-       //for(sy=sdecl; sy!=NULL; sy=sy->sorder)
        for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
        {
                if ((sy->stype == LABEL)
+                       && (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) == 0
                        && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
                        || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
                        || (sy->sattr & COMMON))
@@ -353,9 +345,9 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)())
                        if (buf != NULL)
                                buf = construct(buf, sy, 1);
                }
-               else if ((sy->sattr == (GLOBAL | REFERENCED)) &&  (buf != NULL))
+               else if ((sy->sattr == (GLOBAL | REFERENCED)) &&  (buf != NULL) && (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) == 0)
                {
-                       buf = construct(buf, sy, 0);
+                       buf = construct(buf, sy, 0); // <-- this creates a NON-global symbol...
                        scount++;
                }
        }
@@ -363,6 +355,50 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)())
        return scount;
 }
 
+//
+// Helper function for dsp_lod_symbols
+//
+static uint16_t WriteLODSection(int section, uint16_t symbolCount)
+{
+       for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl)
+       {
+               // Export vanilla labels (but don't make them global). An exception is
+               // made for equates, which are not exported unless they are referenced.
+               if (sy->stype == LABEL && lsym_flag
+                       && (sy->sattr & (DEFINED | REFERENCED)) != 0
+                       && (*sy->sname != '.')
+                       && (sy->sattr & GLOBAL) == 0
+                       && (sy->sattr & (section)))
+               {
+                       sy->senv = symbolCount++;
+                       D_printf("%-19s   I %.6" PRIX64 "\n", sy->sname, sy->svalue);
+               }
+       }
+
+       return symbolCount;
+}
+
+//
+// Dump LOD style symbols into the passed in buffer
+//
+void DumpLODSymbols(void)
+{
+       D_printf("_SYMBOL P\n");
+       uint16_t count = WriteLODSection(M56001P, 0);
+
+       D_printf("_SYMBOL X\n");
+       count = WriteLODSection(M56001X, count);
+
+       D_printf("_SYMBOL Y\n");
+       count = WriteLODSection(M56001Y, count);
+
+       D_printf("_SYMBOL L\n");
+       count = WriteLODSection(M56001L, count);
+
+       // TODO: I've seen _SYMBOL N in there but no idea what symbols it needs...
+       //D_printf("_SYMBOL N\n");
+       //WriteLODSection(M56001?, count);
+}
 
 //
 // Convert string to uppercase
@@ -376,13 +412,11 @@ void ToUppercase(uint8_t * s)
        }
 }
 
-
 //
 // Generate symbol table for listing file
 //
 int symtable(void)
 {
-       extern int pagelen;
        int i;
        int j;
        SYM * q = NULL;
@@ -390,8 +424,8 @@ int symtable(void)
        SYM * r;
        SYM * k;
        SYM * colptr[4];
-       char ln[200];
-       char ln1[200];
+       char ln[1024];
+       char ln1[1024];
        char ln2[20];
        char c, c1;
        WORD w;
@@ -514,7 +548,7 @@ int symtable(void)
                                        strcpy(ln2, "external");
                                else
                                {
-                                       sprintf(ln2, "%08X", q->svalue);
+                                       sprintf(ln2, "%016lX", q->svalue);
                                        ToUppercase(ln2);
                                }
 
@@ -531,3 +565,116 @@ int symtable(void)
        return 0;
 }
 
+SYM * NewDebugSymbol(const uint8_t * str, uint8_t type, uint8_t other, uint16_t desc)
+{
+       SYM * symbol = NewSymbol(str, DBGSYM, 0);
+
+       if (NULL == symbol)
+               fatal("Could not allocate space for debug symbol");
+
+       AddToSymbolDeclarationList(symbol);
+
+       symbol->st_type = type;
+       symbol->st_other = other;
+       symbol->st_desc = desc;
+
+       return symbol;
+}
+
+char *FilePath(const char * fname)
+{
+       char buf1[256];
+       char * fpath;
+       int i, j;
+
+       if ((fpath = realpath(fname, NULL)) != NULL)
+               return fpath;
+
+       for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
+       {
+               j = strlen(buf1);
+
+               // Append path char if necessary
+               if (j > 0 && buf1[j - 1] != SLASHCHAR)
+                       strcat(buf1, SLASHSTRING);
+
+               strcat(buf1, fname);
+
+               if ((fpath = realpath(buf1, NULL)) != NULL)
+                       return fpath;
+       }
+
+       return NULL;
+}
+
+static void GenFileSym(const char * fname, uint8_t type, uint32_t addr, uint32_t sattr)
+{
+       char *fpath;
+
+       if (!(fpath = FilePath(fname)))
+       {
+               // Don't treat this as an error. Any file rmac can read is valid enough.
+               // Just use the relative filename in place of an absolute path for the
+               // debug information.
+               fpath = strdup(fname);
+
+               if (!fpath)
+                       fatal("Could not allocate memory for fake path name");
+       }
+
+       SYM * symbol = NewDebugSymbol(fpath, type, 0, 0);
+
+       free(fpath);
+
+       symbol->svalue = addr;
+       symbol->sattr |= sattr;
+}
+
+void GenMainFileSym(const char * fname)
+{
+       GenFileSym(fname, 0x64 /* N_SO */, 0, DEFINED | TEXT);
+}
+
+void GenLineNoSym(void)
+{
+       uint32_t addr;
+       uint32_t sattr;
+       uint8_t type;
+       SYM * symbol;
+
+       static uint16_t prevlineno = -1;
+       static uint32_t prevaddr = -1;
+       static uint16_t prevfileno = 0;
+
+       if (orgactive)
+       {
+               addr = orgaddr;
+               sattr = ABS | DEFINED | EQUATED;
+               // 0x4c is N_FLINE, function start/body/end line number, repurposed by
+               // MADMAC/ALN for ABS line numbers.
+               type = 0x4c;
+       }
+       else
+       {
+               addr = pcloc;
+               sattr = DEFINED | cursect;
+               type = 0x44; // N_SLINE, text section line number
+       }
+
+       if ((addr == prevaddr) || ((curlineno == prevlineno) && (prevfileno == cfileno)))
+               return;
+
+       prevaddr = addr;
+       prevlineno = curlineno;
+
+       if (prevfileno != cfileno)
+               GenFileSym(curfname, 0x84 /* N_SOL */, addr, sattr);
+
+       prevfileno = cfileno;
+
+       /* MADMAC counts lines starting at 0. Offset curlineno accordingly */
+       symbol = NewDebugSymbol(NULL, type, 0, curlineno - 1);
+
+       symbol->svalue = addr;
+       symbol->sattr |= sattr;
+}