// SYMBOL.C - Symbol Handling
// Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source Utilised with the Kind Permission of Landon Dyer
+// Source utilised with the kind permission of Landon Dyer
//
#include "symbol.h"
#include "procln.h"
#include "error.h"
-static SYM * sytab[NBUCKETS]; // User symbol-table header
-int curenv; // Current enviroment number
-SYM * sorder; // * -> Symbols, in order of reference
-SYM * sordtail; // * -> Last symbol in sorder list
-SYM * sdecl; // * -> Symbols, in order of declaration
-SYM * sdecltail; // * -> Last symbol in sdecl list
+
+// Macros
+#define NBUCKETS 256 // Number of hash buckets (power of 2)
+
+static SYM * symbolTable[NBUCKETS]; // User symbol-table header
+int curenv; // Current enviroment number
+static SYM * sorder; // * -> Symbols, in order of reference
+static SYM * sordtail; // * -> Last symbol in sorder list
+static SYM * sdecl; // * -> Symbols, in order of declaration
+static SYM * sdecltail; // * -> Last symbol in sdecl list
+static uint32_t currentUID; // Symbol UID tracking (done by NewSymbol())
// Tags for marking symbol spaces
// a = absolute
//
-// Initialize Symbol Table
+// Initialize symbol table
//
-void init_sym(void)
+void InitSymbolTable(void)
{
- int i; // Iterator
+ int i; // Iterator
- for(i=0; i<NBUCKETS; ++i) // Initialise symbol hash table
- sytab[i] = NULL;
+ for(i=0; i<NBUCKETS; i++) // Initialise symbol hash table
+ symbolTable[i] = NULL;
- curenv = 1; // Init local symbol enviroment
- sorder = NULL; // Init symbol-reference list
+ curenv = 1; // Init local symbol enviroment
+ sorder = NULL; // Init symbol-reference list
sordtail = NULL;
- sdecl = NULL; // Init symbol-decl list
+ sdecl = NULL; // Init symbol-decl list
sdecltail = NULL;
+ currentUID = 0;
}
//
-// Allocate and Return Pointer to a Copy of a String
+// Hash the print name and enviroment number
//
-char * nstring(char * str)
+int HashSymbol(char * name, int envno)
{
- long i;
- char * s, * d;
-
- for(i=0; str[i]; ++i)
- ;
-
- s = d = amem(i + 1);
-
- while (*str)
- *d++ = *str++;
-
- *d++ = '\0';
-
- return s;
-}
+ int sum, k = 0; // Hash calculation
-
-//
-// Hash the Print Name and Enviroment Number
-//
-int syhash(char * name, int envno)
-{
- int sum, k; // Hash calculation
- k = 0;
-
- for(sum=envno; *name; ++name)
+ for(sum=envno; *name; name++)
{
if (k++ == 1)
sum += *name << 2;
//
// Make a new symbol of type `type' in enviroment `envno'
//
-SYM * newsym(char * name, int type, int envno)
+SYM * NewSymbol(char * name, int type, int envno)
{
- int hash; // Symbol hash value
- SYM * sy; // Pointer to symbol
-
// Allocate the symbol
- sy = (SYM *)amem((long)(sizeof(SYM)));
+ SYM * symbol = malloc(sizeof(SYM));
- if (sy == NULL)
+ if (symbol == NULL)
{
- printf("SYMALLOC ERROR (%s)\n", name);
+ printf("NewSymbol: MALLOC ERROR (symbol=\"%s\")\n", name);
return NULL;
}
- sy->sname = nstring(name);
-
// Fill-in the symbol
- sy->stype = (BYTE)type;
- sy->senv = (WORD)envno;
- sy->sattr = 0;
-
- if (rgpu || rdsp)
- sy->sattre = RISCSYM;
- else
- sy->sattre = 0;
-
- sy->svalue = 0;
+ symbol->sname = strdup(name);
+ symbol->stype = (BYTE)type;
+ symbol->senv = (WORD)envno;
+ symbol->sattr = 0;
+ // Don't do this, it could be a forward reference!
+// symbol->sattr = DEFINED; // We just defined it...
+ // This is a bad assumption. Not every symbol 1st seen in a RISC section is
+ // a RISC symbol!
+// symbol->sattre = (rgpu || rdsp ? RISCSYM : 0);
+ symbol->sattre = 0;
+ symbol->svalue = 0;
+ symbol->sorder = NULL;
+ symbol->uid = currentUID++;
// Install symbol in symbol table
- hash = syhash(name, envno);
- sy->snext = sytab[hash];
- sytab[hash] = sy;
+ int hash = HashSymbol(name, envno);
+ symbol->snext = symbolTable[hash];
+ symbolTable[hash] = symbol;
// Append symbol to symbol-order list
if (sorder == NULL)
- sorder = sy; // Add first symbol
+ sorder = symbol; // Add first symbol
else
- sordtail->sorder = sy; // Or append to tail of list
+ sordtail->sorder = symbol; // Or append to tail of list
- sy->sorder = NULL;
- sordtail = sy;
-
- return sy; // Return pointer to symbol
+ sordtail = symbol;
+ return symbol;
}
//
-// Lookup the symbol `name', of the specified type, with the specified
-// enviroment level
+// Look up the symbol name by its UID and return the pointer to the name.
+// If it's not found, return NULL.
//
-SYM * lookup(char * name, int type, int envno)
+char * GetSymbolNameByUID(uint32_t uid)
{
- SYM * sy; // Symbol record pointer
- int k, sum; // Hash bucket calculation
- char * s; // String pointer
+ //problem is with string lookup, that's why we're writing this
+ //so once this is written, we can put the uid in the token stream
- // Pick a hash-bucket (SAME algorithm as syhash())
- k = 0;
- s = name;
+ // A much better approach to the symbol order list would be to make an
+ // array--that way you can do away with the UIDs and all the rest, and
+ // simply do an array lookup based on position. But meh, let's do this for
+ // now until we can rewrite things so they make sense.
+ SYM * symbol = sorder;
- for(sum=envno; *s;)
+ for(; symbol; symbol=symbol->sorder)
{
- if (k++ == 1)
- sum += *s++ << 2;
- else
- sum += *s++;
+ if (symbol->uid == uid)
+ return symbol->sname;
}
- sy = sytab[sum & (NBUCKETS-1)];
+ return NULL;
+}
+
+
+//
+// Lookup the symbol `name', of the specified type, with the specified
+// enviroment level
+//
+SYM * lookup(char * name, int type, int envno)
+{
+ SYM * symbol = symbolTable[HashSymbol(name, envno)];
// Do linear-search for symbol in bucket
- while (sy != NULL)
+ while (symbol != NULL)
{
- if (sy->stype == type && // Type, envno and name must match
- sy->senv == envno &&
- *name == *sy->sname && // Fast check for first character
- !strcmp(name, sy->sname))
+ if (symbol->stype == type // Type, envno and name must match
+ && symbol->senv == envno
+ && *name == *symbol->sname // Fast check for first character
+ && !strcmp(name, symbol->sname)) // More expensive check
break;
- else
- sy = sy->snext;
+
+ symbol = symbol->snext;
}
- return sy; // Return NULL or matching symbol
+ // Return NULL or matching symbol
+ return symbol;
}
//
// Put symbol on "order-of-declaration" list of symbols
//
-void sym_decl(SYM * sym)
+void AddToSymbolDeclarationList(SYM * symbol)
{
- if (sym->sattr & SDECLLIST)
- return; // Already on list
+ // Don't add if already on list, or it's an equated register/CC
+ if ((symbol->sattr & SDECLLIST)
+ || (symbol->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)))
+ return;
- sym->sattr |= SDECLLIST; // Mark "already on list"
+ // Mark as "on .sdecl list"
+ symbol->sattr |= SDECLLIST;
if (sdecl == NULL)
- sdecl = sym; // First on decl-list
+ sdecl = symbol; // First on decl-list
else
- sdecltail->sdecl = sym; // Add to end of list
+ sdecltail->sdecl = symbol; // Add to end of list
- sym->sdecl = NULL; // Fix up list's tail
- sdecltail = sym;
+ // Fix up list's tail
+ symbol->sdecl = NULL;
+ sdecltail = symbol;
}
//
// Make all referenced, undefined symbols global
//
-int syg_fix(void)
+void ForceUndefinedSymbolsGlobal(void)
{
SYM * sy;
- DEBUG printf("~syg_fix()\n");
+ DEBUG printf("~ForceUndefinedSymbolsGlobal()\n");
// Scan through all symbols;
// If a symbol is REFERENCED but not DEFINED, then make it global.
- for(sy = sorder; sy != NULL; sy = sy->sorder)
+ for(sy=sorder; sy!=NULL; sy=sy->sorder)
{
if (sy->stype == LABEL && sy->senv == 0
- && ((sy->sattr & (REFERENCED|DEFINED)) == REFERENCED))
+ && ((sy->sattr & (REFERENCED | DEFINED)) == REFERENCED))
sy->sattr |= GLOBAL;
}
-
- return 0;
}
//
int uc_string(char * s)
{
- for(; *s; ++s)
+ for(; *s; s++)
{
if (*s >= 'a' && *s <= 'z')
*s -= 32;
// number is put in `.senv'. Return the number of symbols that will be in the
// symbol table.
//
-int sy_assign(char * buf, char *(*constr)())
+int sy_assign(char * buf, char *(* constr)())
{
SYM * sy;
- int scount;
- //int i;
-
- scount = 0;
+ int scount = 0;
if (buf == NULL)
{
// Append all symbols not appearing on the .sdecl list to the end of
// the .sdecl list
for(sy=sorder; sy!=NULL; sy=sy->sorder)
- {
- // Essentially the same as 'sym_decl()' above:
- if (sy->sattr & SDECLLIST)
- continue; // Already on list
-
- sy->sattr |= SDECLLIST; // Mark "on the list"
-
- if (sdecl == NULL)
- sdecl = sy; // First on decl-list
- else
- sdecltail->sdecl = sy; // Add to end of list
-
- sy->sdecl = NULL; // Fix up list's tail
- sdecltail = sy;
- }
+ 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(sy=sdecl; sy!=NULL; sy=sy->sdecl)
{
- if (sy->sattre & UNDEF_EQUR)
- continue; // Don't want undefined on our list
+ // Don't want register/CC or undefined on our list
+//these should already be rejected above...
+// if (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)))
+// continue;
- if (sy->sattre & 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))
+ && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
+ || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
|| (sy->sattr & COMMON))
{
sy->senv = (WORD)scount++;
// 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
+ && (sy->sattr & (DEFINED | REFERENCED)) != 0
&& (!as68_flag || *sy->sname != 'L'))
{
sy->senv = (WORD)scount++;
- if (buf != NULL) buf = (*constr)(buf, sy, 0);
+
+ if (buf != NULL)
+ buf = (*constr)(buf, sy, 0);
}
}
// Allocate storage for list headers and partition all labels.
// Throw away macros and macro arguments.
- sy = (SYM **)amem((LONG)(128 * sizeof(LONG)));
+ sy = (SYM **)malloc(128 * sizeof(LONG));
for(i=0; i<128; ++i)
sy[i] = NULL;
for(i=0; i<NBUCKETS; ++i)
{
- for(p=sytab[i]; p!=NULL; p=k)
+ for(p=symbolTable[i]; p!=NULL; p=k)
{
k = p->snext;
j = *p->sname;
r = NULL;
- if (p->stype != LABEL)
- continue; // Ignore non-labels
-
- if (p->sattre & UNDEF_EQUR)
+ // Ignore non-labels
+ if ((p->stype != LABEL) || (p->sattre & UNDEF_EQUR))
continue;
for(q=sy[j]; q!=NULL; q=q->snext)
{
if (strcmp(p->sname, q->sname) < 0)
break;
- else
- r = q;
+
+ r = q;
}
if (r == NULL)
- { // Insert at front of list
+ {
+ // Insert at front of list
p->snext = sy[j];
sy[j] = p;
}
else
- { // Insert in middle or append to list
+ {
+ // Insert in middle or append to list
p->snext = r->snext;
r->snext = p;
}
strcpy(ln2, "external");
else
{
- sprintf(ln2, "%08ux", q->svalue);
+ sprintf(ln2, "%08X", q->svalue);
uc_string(ln2);
}
return 0;
}
+