]> Shamusworld >> Repos - rmac/blob - symbol.c
First working 64-bit version of RMAC
[rmac] / symbol.c
1 //
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
7 //
8
9 #include "symbol.h"
10 #include "listing.h"
11 #include "procln.h"
12 #include "error.h"
13
14 // Macros
15 #define NBUCKETS 256                                    // Number of hash buckets (power of 2)
16
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
23
24 // Tags for marking symbol spaces
25 // a = absolute
26 // t = text
27 // d = data
28 // ! = "impossible!"
29 // b = BSS
30 static char tdb_text[8] = {
31    'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
32 };
33
34
35 //
36 // Initialize Symbol Table
37 //
38 void InitSymbolTable(void)
39 {
40         int i;                                                                  // Iterator
41
42         for(i=0; i<NBUCKETS; i++)                               // Initialise symbol hash table
43                 symbolTable[i] = NULL;
44
45         curenv = 1;                                                             // Init local symbol enviroment
46         sorder = NULL;                                                  // Init symbol-reference list
47         sordtail = NULL;
48         sdecl = NULL;                                                   // Init symbol-decl list
49         sdecltail = NULL;
50 }
51
52
53 //
54 // Hash the Print Name and Enviroment Number
55 //
56 int HashSymbol(char * name, int envno)
57 {
58         int sum, k = 0;                                                 // Hash calculation
59
60         for(sum=envno; *name; name++)
61         {
62                 if (k++ == 1)
63                         sum += *name << 2;
64                 else
65                         sum += *name;
66         }
67
68         return sum & (NBUCKETS - 1);
69 }
70
71
72 //
73 // Make a new symbol of type `type' in enviroment `envno'
74 //
75 SYM * NewSymbol(char * name, int type, int envno)
76 {
77         // Allocate the symbol
78         SYM * symbol = malloc(sizeof(SYM));
79
80         if (symbol == NULL)
81         {
82                 printf("SYMALLOC ERROR (%s)\n", name);
83                 return NULL;
84         }
85
86         symbol->sname = strdup(name);
87
88         // Fill-in the symbol
89         symbol->stype  = (BYTE)type;
90         symbol->senv   = (WORD)envno;
91         symbol->sattr  = 0;
92         symbol->sattre = (rgpu || rdsp ? RISCSYM : 0);
93         symbol->svalue = 0;
94
95         // Install symbol in symbol table
96         int hash = HashSymbol(name, envno);
97         symbol->snext = symbolTable[hash];
98         symbolTable[hash] = symbol;
99
100         // Append symbol to symbol-order list
101         if (sorder == NULL)
102                 sorder = symbol;                                        // Add first symbol 
103         else
104                 sordtail->sorder = symbol;                      // Or append to tail of list
105
106         symbol->sorder = NULL;
107         sordtail = symbol;
108
109         return symbol;
110 }
111
112
113 //
114 // Lookup the symbol `name', of the specified type, with the specified
115 // enviroment level
116 //
117 SYM * lookup(char * name, int type, int envno)
118 {
119 #if 0
120         SYM * sy;                                   // Symbol record pointer
121         int k, sum;                                 // Hash bucket calculation
122         char * s;                                   // String pointer
123
124         // Pick a hash-bucket (SAME algorithm as HashSymbol())
125         k = 0;
126         s = name;
127
128         for(sum=envno; *s;)
129         {
130                 if (k++ == 1)
131                         sum += *s++ << 2;
132                 else
133                         sum += *s++;
134         }
135
136         sy = symbolTable[sum & (NBUCKETS-1)];
137 #else
138         SYM * symbol = symbolTable[HashSymbol(name, envno)];
139 #endif
140
141         // Do linear-search for symbol in bucket
142         while (symbol != NULL)
143         {
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))
148                         break;
149                 else
150                         symbol = symbol->snext;
151         }
152
153         return symbol;                                                  // Return NULL or matching symbol
154 }
155
156
157 //
158 // Put symbol on "order-of-declaration" list of symbols
159 //
160 void sym_decl(SYM * sym)
161 {
162         if (sym->sattr & SDECLLIST)
163                 return;                                                         // Already on list
164
165         sym->sattr |= SDECLLIST;                                // Mark "already on list"
166
167         if (sdecl == NULL)
168                 sdecl = sym;                                            // First on decl-list
169         else 
170                 sdecltail->sdecl = sym;                         // Add to end of list
171
172         sym->sdecl = NULL;                                              // Fix up list's tail
173         sdecltail = sym;
174 }
175
176
177 //
178 // Make all referenced, undefined symbols global
179 //
180 int syg_fix(void)
181 {
182         SYM * sy;
183
184         DEBUG printf("~syg_fix()\n");
185
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)
189         {
190                 if (sy->stype == LABEL && sy->senv == 0
191                         && ((sy->sattr & (REFERENCED | DEFINED)) == REFERENCED))
192                         sy->sattr |= GLOBAL;
193         }
194
195         return 0;
196 }
197
198
199 //
200 // Convert string to uppercase
201 //
202 int uc_string(char * s)
203 {
204         for(; *s; s++)
205         {
206                 if (*s >= 'a' && *s <= 'z')
207                         *s -= 32;
208         }
209
210         return 0;
211 }
212
213
214 //
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
217 // symbol table.
218 //
219 int sy_assign(char * buf, char *(* constr)())
220 {
221         SYM * sy;
222         int scount;
223         //int i;
224
225         scount = 0;
226
227         if (buf == NULL)
228         {
229                 // Append all symbols not appearing on the .sdecl list to the end of
230                 // the .sdecl list
231                 for(sy=sorder; sy!=NULL; sy=sy->sorder)
232                 {
233                         // Essentially the same as 'sym_decl()' above:
234                         if (sy->sattr & SDECLLIST)
235                                 continue;                // Already on list 
236
237                         sy->sattr |= SDECLLIST;                            // Mark "on the list"
238
239                         if (sdecl == NULL)
240                                 sdecl = sy;                      // First on decl-list 
241                         else
242                                 sdecltail->sdecl = sy;                        // Add to end of list
243
244                         sy->sdecl = NULL;                                  // Fix up list's tail
245                         sdecltail = sy;
246                 }
247         }
248
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)
252         {
253                 if (sy->sattre & UNDEF_EQUR)
254                         continue;                 // Don't want undefined on our list
255
256                 if (sy->sattre & UNDEF_CC)
257                         continue;                   
258                 
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))
264                 {
265                         sy->senv = (WORD)scount++;
266
267                         if (buf != NULL)
268                                 buf = (*constr)(buf, sy, 1);
269                 }
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'))
275                 {
276                         sy->senv = (WORD)scount++;
277                         if (buf != NULL) buf = (*constr)(buf, sy, 0);
278                 }
279         }
280
281         return scount;
282 }
283
284
285 //
286 // Generate symbol table for listing file
287 //
288 int symtable(void)
289 {
290         int i;
291         int j;
292         SYM * q = NULL;
293         SYM * p;
294         SYM * r;
295         SYM * k;
296         SYM ** sy;
297         SYM * colptr[4];
298         char ln[150];
299         char ln1[150];
300         char ln2[20];
301         char c, c1;
302         WORD w;
303         int ww;
304         int colhei;
305         extern int pagelen;
306
307         colhei = pagelen - 5;
308
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));
313
314         for(i=0; i<128; ++i)
315                 sy[i] = NULL;
316
317         for(i=0; i<NBUCKETS; ++i)
318         {
319                 for(p=symbolTable[i]; p!=NULL; p=k)
320                 {
321                         k = p->snext;
322                         j = *p->sname;
323                         r = NULL;
324
325                         if (p->stype != LABEL)
326                                 continue;                   // Ignore non-labels
327
328                         if (p->sattre & UNDEF_EQUR)
329                                 continue;
330
331                         for(q=sy[j]; q!=NULL; q=q->snext)
332                         {
333                                 if (strcmp(p->sname, q->sname) < 0)
334                                         break;
335                                 else
336                                         r = q;
337                         }
338
339                         if (r == NULL)
340                         {                               // Insert at front of list
341                                 p->snext = sy[j];
342                                 sy[j] = p;
343                         }
344                         else
345                         {                               // Insert in middle or append to list
346                                 p->snext = r->snext;
347                                 r->snext = p;
348                         }
349                 }
350         }
351
352         // Link all symbols onto one list again
353         p = NULL;
354
355         for(i=0; i<128; ++i)
356         {
357                 if ((r = sy[i]) != NULL)
358                 {
359                         if (p == NULL)
360                                 q = r;
361                         else
362                                 q->snext = r;
363
364                         while (q->snext != NULL)
365                                 q = q->snext;
366
367                         if (p == NULL)
368                                 p = r;
369                 }
370         }
371
372         eject();
373         strcpy(subttl, "Symbol Table");
374
375         while (p != NULL)
376         {
377                 for(i=0; i<4; ++i)
378                 {
379                         colptr[i] = p;
380
381                         for(j=0; j<colhei; ++j)
382                         {
383                                 if (p == NULL)
384                                         break;
385                                 else
386                                         p = p->snext;
387                         }
388                 }
389
390                 for(i=0; i<colhei; ++i)
391                 {
392                         *ln = EOS;
393
394                         if (colptr[0] == NULL)
395                                 break;
396
397                         for(j=0; j<4; ++j)
398                         {
399                                 if ((q = colptr[j]) == NULL)
400                                         break;
401
402                                 colptr[j] = q->snext;
403                                 w = q->sattr;
404                                 ww = q->sattre;
405                                 // Pick a tag:
406                                 // c    common
407                                 // x    external reference
408                                 // g    global (export)
409                                 // space        nothing special
410                                 c1 = SPACE;
411                                 c = SPACE;
412
413                                 if (w & COMMON)
414                                         c = 'c';
415                                 else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
416                                         c = 'x';
417                                 else if (w & GLOBAL)
418                                         c = 'g';
419
420                                 c1 = tdb_text[w & TDB];
421
422                                 if (c == 'x')
423                                         strcpy(ln2, "external");
424                                 else
425                                 {
426                                         sprintf(ln2, "%08ux", q->svalue);
427                                         uc_string(ln2);
428                                 }
429
430                                 sprintf(ln1, "  %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);
431                                 strcat(ln, ln1);
432                         }
433
434                         ship_ln(ln);
435                 }
436
437                 eject();
438         }
439
440         return 0;
441 }