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
16 #define NBUCKETS 256 // Number of hash buckets (power of 2)
18 static SYM * symbolTable[NBUCKETS]; // User symbol-table header
19 int curenv; // Current enviroment number
20 static SYM * sorder; // * -> Symbols, in order of reference
21 static SYM * sordtail; // * -> Last symbol in sorder list
22 static SYM * sdecl; // * -> Symbols, in order of declaration
23 static SYM * sdecltail; // * -> Last symbol in sdecl list
24 static uint32_t currentUID; // Symbol UID tracking (done by NewSymbol())
26 // Tags for marking symbol spaces
32 static char tdb_text[8] = {
33 'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
38 // Initialize Symbol Table
40 void InitSymbolTable(void)
44 for(i=0; i<NBUCKETS; i++) // Initialise symbol hash table
45 symbolTable[i] = NULL;
47 curenv = 1; // Init local symbol enviroment
48 sorder = NULL; // Init symbol-reference list
50 sdecl = NULL; // Init symbol-decl list
57 // Hash the Print Name and Enviroment Number
59 int HashSymbol(char * name, int envno)
61 int sum, k = 0; // Hash calculation
63 for(sum=envno; *name; name++)
71 return sum & (NBUCKETS - 1);
76 // Make a new symbol of type `type' in enviroment `envno'
78 SYM * NewSymbol(char * name, int type, int envno)
80 // Allocate the symbol
81 SYM * symbol = malloc(sizeof(SYM));
85 printf("NewSymbol: MALLOC ERROR (symbol=\"%s\")\n", name);
90 symbol->sname = strdup(name);
91 symbol->stype = (BYTE)type;
92 symbol->senv = (WORD)envno;
94 //we don't do this, it could be a forward reference!
95 // symbol->sattr = DEFINED; // We just defined it...
96 // This is a bad assumption. Not every symbol 1st seen in a RISC section is
98 // symbol->sattre = (rgpu || rdsp ? RISCSYM : 0);
101 symbol->sorder = NULL;
102 symbol->uid = currentUID++;
104 // Install symbol in symbol table
105 int hash = HashSymbol(name, envno);
106 symbol->snext = symbolTable[hash];
107 symbolTable[hash] = symbol;
109 // Append symbol to symbol-order list
111 sorder = symbol; // Add first symbol
113 sordtail->sorder = symbol; // Or append to tail of list
121 // Look up the symbol name by its UID and return the pointer to the name.
122 // If it's not found, return NULL.
124 char * GetSymbolNameByUID(uint32_t uid)
126 //problem is with string lookup, that's why we're writing this
127 //so once this is written, we can put the uid in the token stream
129 // A much better approach to the symbol order list would be to make an
130 // array--that way you can do away with the UIDs and all the rest, and
131 // simply do an array lookup based on position. But meh, let's do this for
132 // now until we can rewrite things so they make sense.
133 SYM * symbol = sorder;
135 for(; symbol; symbol=symbol->sorder)
137 if (symbol->uid == uid)
138 return symbol->sname;
146 // Lookup the symbol `name', of the specified type, with the specified
149 SYM * lookup(char * name, int type, int envno)
151 SYM * symbol = symbolTable[HashSymbol(name, envno)];
153 // Do linear-search for symbol in bucket
154 while (symbol != NULL)
156 if (symbol->stype == type // Type, envno and name must match
157 && symbol->senv == envno
158 && *name == *symbol->sname // Fast check for first character
159 && !strcmp(name, symbol->sname)) // More expensive check
162 symbol = symbol->snext;
165 // Return NULL or matching symbol
171 // Put symbol on "order-of-declaration" list of symbols
173 //void sym_decl(SYM * symbol)
174 void AddToSymbolOrderList(SYM * symbol)
176 if (symbol->sattr & SDECLLIST)
177 return; // Already on list
179 symbol->sattr |= SDECLLIST; // Mark "already on list"
182 sdecl = symbol; // First on decl-list
184 sdecltail->sdecl = symbol; // Add to end of list
186 symbol->sdecl = NULL; // Fix up list's tail
192 // Make all referenced, undefined symbols global
198 DEBUG printf("~syg_fix()\n");
200 // Scan through all symbols;
201 // If a symbol is REFERENCED but not DEFINED, then make it global.
202 for(sy=sorder; sy!=NULL; sy=sy->sorder)
204 if (sy->stype == LABEL && sy->senv == 0
205 && ((sy->sattr & (REFERENCED | DEFINED)) == REFERENCED))
214 // Convert string to uppercase
216 int uc_string(char * s)
220 if (*s >= 'a' && *s <= 'z')
229 // Assign numbers to symbols that are to be exported or imported. The symbol
230 // number is put in `.senv'. Return the number of symbols that will be in the
233 int sy_assign(char * buf, char *(* constr)())
243 // Append all symbols not appearing on the .sdecl list to the end of
245 for(sy=sorder; sy!=NULL; sy=sy->sorder)
247 // Essentially the same as 'sym_decl()' above:
248 if (sy->sattr & SDECLLIST)
249 continue; // Already on list
251 sy->sattr |= SDECLLIST; // Mark "on the list"
254 sdecl = sy; // First on decl-list
256 sdecltail->sdecl = sy; // Add to end of list
258 sy->sdecl = NULL; // Fix up list's tail
263 // Run through all symbols (now on the .sdecl list) and assign numbers to
264 // them. We also pick which symbols should be global or not here.
265 for(sy=sdecl; sy!=NULL; sy=sy->sdecl)
267 if (sy->sattre & UNDEF_EQUR)
268 continue; // Don't want undefined on our list
270 if (sy->sattre & UNDEF_CC)
273 // Export or import external references, and export COMMON blocks.
274 if ((sy->stype == LABEL)
275 && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
276 || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
277 || (sy->sattr & COMMON))
279 sy->senv = (WORD)scount++;
282 buf = (*constr)(buf, sy, 1);
284 // Export vanilla labels (but don't make them global). An exception is
285 // made for equates, which are not exported unless they are referenced.
286 else if (sy->stype == LABEL && lsym_flag
287 && (sy->sattr & (DEFINED | REFERENCED)) != 0
288 && (!as68_flag || *sy->sname != 'L'))
290 sy->senv = (WORD)scount++;
291 if (buf != NULL) buf = (*constr)(buf, sy, 0);
300 // Generate symbol table for listing file
321 colhei = pagelen - 5;
323 // Allocate storage for list headers and partition all labels.
324 // Throw away macros and macro arguments.
325 // sy = (SYM **)amem((LONG)(128 * sizeof(LONG)));
326 sy = (SYM **)malloc(128 * sizeof(LONG));
331 for(i=0; i<NBUCKETS; ++i)
333 for(p=symbolTable[i]; p!=NULL; p=k)
339 if (p->stype != LABEL)
340 continue; // Ignore non-labels
342 if (p->sattre & UNDEF_EQUR)
345 for(q=sy[j]; q!=NULL; q=q->snext)
347 if (strcmp(p->sname, q->sname) < 0)
354 { // Insert at front of list
359 { // Insert in middle or append to list
366 // Link all symbols onto one list again
371 if ((r = sy[i]) != NULL)
378 while (q->snext != NULL)
387 strcpy(subttl, "Symbol Table");
395 for(j=0; j<colhei; ++j)
404 for(i=0; i<colhei; ++i)
408 if (colptr[0] == NULL)
413 if ((q = colptr[j]) == NULL)
416 colptr[j] = q->snext;
421 // x external reference
423 // space nothing special
429 else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
434 c1 = tdb_text[w & TDB];
437 strcpy(ln2, "external");
440 sprintf(ln2, "%08X", q->svalue);
444 sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);