2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // SYMBOL.C - Symbol Handling
4 // Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
15 #define NBUCKETS 256 // Number of hash buckets (power of 2)
17 static SYM * symbolTable[NBUCKETS]; // User symbol-table header
18 int curenv; // Current enviroment number
19 static SYM * sorder; // * -> Symbols, in order of reference
20 static SYM * sordtail; // * -> Last symbol in sorder list
21 static SYM * sdecl; // * -> Symbols, in order of declaration
22 static SYM * sdecltail; // * -> Last symbol in sdecl list
24 // Tags for marking symbol spaces
30 static char tdb_text[8] = {
31 'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
36 // Initialize Symbol Table
38 void InitSymbolTable(void)
42 for(i=0; i<NBUCKETS; i++) // Initialise symbol hash table
43 symbolTable[i] = NULL;
45 curenv = 1; // Init local symbol enviroment
46 sorder = NULL; // Init symbol-reference list
48 sdecl = NULL; // Init symbol-decl list
54 // Hash the Print Name and Enviroment Number
56 int HashSymbol(char * name, int envno)
58 int sum, k = 0; // Hash calculation
60 for(sum=envno; *name; name++)
68 return sum & (NBUCKETS - 1);
73 // Make a new symbol of type `type' in enviroment `envno'
75 SYM * NewSymbol(char * name, int type, int envno)
77 // Allocate the symbol
78 SYM * symbol = malloc(sizeof(SYM));
82 printf("SYMALLOC ERROR (%s)\n", name);
86 symbol->sname = strdup(name);
89 symbol->stype = (BYTE)type;
90 symbol->senv = (WORD)envno;
92 symbol->sattre = (rgpu || rdsp ? RISCSYM : 0);
95 // Install symbol in symbol table
96 int hash = HashSymbol(name, envno);
97 symbol->snext = symbolTable[hash];
98 symbolTable[hash] = symbol;
100 // Append symbol to symbol-order list
102 sorder = symbol; // Add first symbol
104 sordtail->sorder = symbol; // Or append to tail of list
106 symbol->sorder = NULL;
114 // Lookup the symbol `name', of the specified type, with the specified
117 SYM * lookup(char * name, int type, int envno)
120 SYM * sy; // Symbol record pointer
121 int k, sum; // Hash bucket calculation
122 char * s; // String pointer
124 // Pick a hash-bucket (SAME algorithm as HashSymbol())
136 sy = symbolTable[sum & (NBUCKETS-1)];
138 SYM * symbol = symbolTable[HashSymbol(name, envno)];
141 // Do linear-search for symbol in bucket
142 while (symbol != NULL)
144 if (symbol->stype == type // Type, envno and name must match
145 && symbol->senv == envno
146 && *name == *symbol->sname // Fast check for first character
147 && !strcmp(name, symbol->sname))
150 symbol = symbol->snext;
153 return symbol; // Return NULL or matching symbol
158 // Put symbol on "order-of-declaration" list of symbols
160 void sym_decl(SYM * sym)
162 if (sym->sattr & SDECLLIST)
163 return; // Already on list
165 sym->sattr |= SDECLLIST; // Mark "already on list"
168 sdecl = sym; // First on decl-list
170 sdecltail->sdecl = sym; // Add to end of list
172 sym->sdecl = NULL; // Fix up list's tail
178 // Make all referenced, undefined symbols global
184 DEBUG printf("~syg_fix()\n");
186 // Scan through all symbols;
187 // If a symbol is REFERENCED but not DEFINED, then make it global.
188 for(sy=sorder; sy!=NULL; sy=sy->sorder)
190 if (sy->stype == LABEL && sy->senv == 0
191 && ((sy->sattr & (REFERENCED | DEFINED)) == REFERENCED))
200 // Convert string to uppercase
202 int uc_string(char * s)
206 if (*s >= 'a' && *s <= 'z')
215 // Assign numbers to symbols that are to be exported or imported. The symbol
216 // number is put in `.senv'. Return the number of symbols that will be in the
219 int sy_assign(char * buf, char *(* constr)())
229 // Append all symbols not appearing on the .sdecl list to the end of
231 for(sy=sorder; sy!=NULL; sy=sy->sorder)
233 // Essentially the same as 'sym_decl()' above:
234 if (sy->sattr & SDECLLIST)
235 continue; // Already on list
237 sy->sattr |= SDECLLIST; // Mark "on the list"
240 sdecl = sy; // First on decl-list
242 sdecltail->sdecl = sy; // Add to end of list
244 sy->sdecl = NULL; // Fix up list's tail
249 // Run through all symbols (now on the .sdecl list) and assign numbers to
250 // them. We also pick which symbols should be global or not here.
251 for(sy=sdecl; sy!=NULL; sy=sy->sdecl)
253 if (sy->sattre & UNDEF_EQUR)
254 continue; // Don't want undefined on our list
256 if (sy->sattre & UNDEF_CC)
259 // Export or import external references, and export COMMON blocks.
260 if ((sy->stype == LABEL)
261 && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
262 || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
263 || (sy->sattr & COMMON))
265 sy->senv = (WORD)scount++;
268 buf = (*constr)(buf, sy, 1);
270 // Export vanilla labels (but don't make them global). An exception is
271 // made for equates, which are not exported unless they are referenced.
272 else if (sy->stype == LABEL && lsym_flag
273 && (sy->sattr & (DEFINED | REFERENCED)) != 0
274 && (!as68_flag || *sy->sname != 'L'))
276 sy->senv = (WORD)scount++;
277 if (buf != NULL) buf = (*constr)(buf, sy, 0);
286 // Generate symbol table for listing file
307 colhei = pagelen - 5;
309 // Allocate storage for list headers and partition all labels.
310 // Throw away macros and macro arguments.
311 // sy = (SYM **)amem((LONG)(128 * sizeof(LONG)));
312 sy = (SYM **)malloc(128 * sizeof(LONG));
317 for(i=0; i<NBUCKETS; ++i)
319 for(p=symbolTable[i]; p!=NULL; p=k)
325 if (p->stype != LABEL)
326 continue; // Ignore non-labels
328 if (p->sattre & UNDEF_EQUR)
331 for(q=sy[j]; q!=NULL; q=q->snext)
333 if (strcmp(p->sname, q->sname) < 0)
340 { // Insert at front of list
345 { // Insert in middle or append to list
352 // Link all symbols onto one list again
357 if ((r = sy[i]) != NULL)
364 while (q->snext != NULL)
373 strcpy(subttl, "Symbol Table");
381 for(j=0; j<colhei; ++j)
390 for(i=0; i<colhei; ++i)
394 if (colptr[0] == NULL)
399 if ((q = colptr[j]) == NULL)
402 colptr[j] = q->snext;
407 // x external reference
409 // space nothing special
415 else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
420 c1 = tdb_text[w & TDB];
423 strcpy(ln2, "external");
426 sprintf(ln2, "%08ux", q->svalue);
430 sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);