]> Shamusworld >> Repos - rmac/blob - symbol.c
Forgot to bump patch level on version.h :-P
[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 static uint32_t currentUID;                             // Symbol UID tracking (done by NewSymbol())
24
25 // Tags for marking symbol spaces
26 // a = absolute
27 // t = text
28 // d = data
29 // ! = "impossible!"
30 // b = BSS
31 static char tdb_text[8] = {
32    'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
33 };
34
35
36 //
37 // Initialize Symbol Table
38 //
39 void InitSymbolTable(void)
40 {
41         int i;                                                                  // Iterator
42
43         for(i=0; i<NBUCKETS; i++)                               // Initialise symbol hash table
44                 symbolTable[i] = NULL;
45
46         curenv = 1;                                                             // Init local symbol enviroment
47         sorder = NULL;                                                  // Init symbol-reference list
48         sordtail = NULL;
49         sdecl = NULL;                                                   // Init symbol-decl list
50         sdecltail = NULL;
51         currentUID = 0;
52 }
53
54
55 //
56 // Hash the Print Name and Enviroment Number
57 //
58 int HashSymbol(char * name, int envno)
59 {
60         int sum, k = 0;                                                 // Hash calculation
61
62         for(sum=envno; *name; name++)
63         {
64                 if (k++ == 1)
65                         sum += *name << 2;
66                 else
67                         sum += *name;
68         }
69
70         return sum & (NBUCKETS - 1);
71 }
72
73
74 //
75 // Make a new symbol of type `type' in enviroment `envno'
76 //
77 SYM * NewSymbol(char * name, int type, int envno)
78 {
79         // Allocate the symbol
80         SYM * symbol = malloc(sizeof(SYM));
81
82         if (symbol == NULL)
83         {
84                 printf("NewSymbol: MALLOC ERROR (symbol=\"%s\")\n", name);
85                 return NULL;
86         }
87
88         // Fill-in the symbol
89         symbol->sname  = strdup(name);
90         symbol->stype  = (BYTE)type;
91         symbol->senv   = (WORD)envno;
92         symbol->sattr  = 0;
93         symbol->sattre = (rgpu || rdsp ? RISCSYM : 0);
94         symbol->svalue = 0;
95         symbol->sorder = NULL;
96         symbol->uid    = currentUID++;
97
98         // Install symbol in symbol table
99         int hash = HashSymbol(name, envno);
100         symbol->snext = symbolTable[hash];
101         symbolTable[hash] = symbol;
102
103         // Append symbol to symbol-order list
104         if (sorder == NULL)
105                 sorder = symbol;                                        // Add first symbol 
106         else
107                 sordtail->sorder = symbol;                      // Or append to tail of list
108
109         sordtail = symbol;
110         return symbol;
111 }
112
113
114 //
115 // Look up the symbol name by its UID and return the pointer to the name.
116 // If it's not found, return NULL.
117 //
118 char * GetSymbolNameByUID(uint32_t uid)
119 {
120         //problem is with string lookup, that's why we're writing this
121         //so once this is written, we can put the uid in the token stream
122
123         // A much better approach to the symbol order list would be to make an
124         // array--that way you can do away with the UIDs and all the rest, and
125         // simply do an array lookup based on position. But meh, let's do this for
126         // now until we can rewrite things so they make sense.
127         SYM * symbol = sorder;
128
129         for(; symbol; symbol=symbol->sorder)
130         {
131                 if (symbol->uid == uid)
132                         return symbol->sname;
133         }
134
135         return NULL;
136 }
137
138
139 //
140 // Lookup the symbol `name', of the specified type, with the specified
141 // enviroment level
142 //
143 SYM * lookup(char * name, int type, int envno)
144 {
145         SYM * symbol = symbolTable[HashSymbol(name, envno)];
146
147         // Do linear-search for symbol in bucket
148         while (symbol != NULL)
149         {
150                 if (symbol->stype == type                       // Type, envno and name must match
151                         && symbol->senv  == envno
152                         && *name == *symbol->sname              // Fast check for first character
153                         && !strcmp(name, symbol->sname))
154                         break;
155
156                 symbol = symbol->snext;
157         }
158
159         return symbol;                                                  // Return NULL or matching symbol
160 }
161
162
163 //
164 // Put symbol on "order-of-declaration" list of symbols
165 //
166 void sym_decl(SYM * symbol)
167 {
168         if (symbol->sattr & SDECLLIST)
169                 return;                                                         // Already on list
170
171         symbol->sattr |= SDECLLIST;                             // Mark "already on list"
172
173         if (sdecl == NULL)
174                 sdecl = symbol;                                         // First on decl-list
175         else 
176                 sdecltail->sdecl = symbol;                      // Add to end of list
177
178         symbol->sdecl = NULL;                                   // Fix up list's tail
179         sdecltail = symbol;
180 }
181
182
183 //
184 // Make all referenced, undefined symbols global
185 //
186 int syg_fix(void)
187 {
188         SYM * sy;
189
190         DEBUG printf("~syg_fix()\n");
191
192         // Scan through all symbols;
193         // If a symbol is REFERENCED but not DEFINED, then make it global.
194         for(sy=sorder; sy!=NULL; sy=sy->sorder)
195         {
196                 if (sy->stype == LABEL && sy->senv == 0
197                         && ((sy->sattr & (REFERENCED | DEFINED)) == REFERENCED))
198                         sy->sattr |= GLOBAL;
199         }
200
201         return 0;
202 }
203
204
205 //
206 // Convert string to uppercase
207 //
208 int uc_string(char * s)
209 {
210         for(; *s; s++)
211         {
212                 if (*s >= 'a' && *s <= 'z')
213                         *s -= 32;
214         }
215
216         return 0;
217 }
218
219
220 //
221 // Assign numbers to symbols that are to be exported or imported. The symbol
222 // number is put in `.senv'. Return the number of symbols that will be in the
223 // symbol table.
224 //
225 int sy_assign(char * buf, char *(* constr)())
226 {
227         SYM * sy;
228         int scount;
229         //int i;
230
231         scount = 0;
232
233         if (buf == NULL)
234         {
235                 // Append all symbols not appearing on the .sdecl list to the end of
236                 // the .sdecl list
237                 for(sy=sorder; sy!=NULL; sy=sy->sorder)
238                 {
239                         // Essentially the same as 'sym_decl()' above:
240                         if (sy->sattr & SDECLLIST)
241                                 continue;                // Already on list 
242
243                         sy->sattr |= SDECLLIST;                            // Mark "on the list"
244
245                         if (sdecl == NULL)
246                                 sdecl = sy;                      // First on decl-list 
247                         else
248                                 sdecltail->sdecl = sy;                        // Add to end of list
249
250                         sy->sdecl = NULL;                                  // Fix up list's tail
251                         sdecltail = sy;
252                 }
253         }
254
255         // Run through all symbols (now on the .sdecl list) and assign numbers to
256         // them. We also pick which symbols should be global or not here.
257         for(sy=sdecl; sy!=NULL; sy=sy->sdecl)
258         {
259                 if (sy->sattre & UNDEF_EQUR)
260                         continue;                 // Don't want undefined on our list
261
262                 if (sy->sattre & UNDEF_CC)
263                         continue;                   
264                 
265                 // Export or import external references, and export COMMON blocks.
266                 if ((sy->stype == LABEL)
267                         && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED)
268                         || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED))
269                         || (sy->sattr & COMMON))
270                 {
271                         sy->senv = (WORD)scount++;
272
273                         if (buf != NULL)
274                                 buf = (*constr)(buf, sy, 1);
275                 }
276                 // Export vanilla labels (but don't make them global). An exception is
277                 // made for equates, which are not exported unless they are referenced.
278                 else if (sy->stype == LABEL && lsym_flag
279                         && (sy->sattr & (DEFINED | REFERENCED)) != 0
280                         && (!as68_flag || *sy->sname != 'L'))
281                 {
282                         sy->senv = (WORD)scount++;
283                         if (buf != NULL) buf = (*constr)(buf, sy, 0);
284                 }
285         }
286
287         return scount;
288 }
289
290
291 //
292 // Generate symbol table for listing file
293 //
294 int symtable(void)
295 {
296         int i;
297         int j;
298         SYM * q = NULL;
299         SYM * p;
300         SYM * r;
301         SYM * k;
302         SYM ** sy;
303         SYM * colptr[4];
304         char ln[150];
305         char ln1[150];
306         char ln2[20];
307         char c, c1;
308         WORD w;
309         int ww;
310         int colhei;
311         extern int pagelen;
312
313         colhei = pagelen - 5;
314
315         // Allocate storage for list headers and partition all labels.  
316         // Throw away macros and macro arguments.
317 //      sy = (SYM **)amem((LONG)(128 * sizeof(LONG)));
318         sy = (SYM **)malloc(128 * sizeof(LONG));
319
320         for(i=0; i<128; ++i)
321                 sy[i] = NULL;
322
323         for(i=0; i<NBUCKETS; ++i)
324         {
325                 for(p=symbolTable[i]; p!=NULL; p=k)
326                 {
327                         k = p->snext;
328                         j = *p->sname;
329                         r = NULL;
330
331                         if (p->stype != LABEL)
332                                 continue;                   // Ignore non-labels
333
334                         if (p->sattre & UNDEF_EQUR)
335                                 continue;
336
337                         for(q=sy[j]; q!=NULL; q=q->snext)
338                         {
339                                 if (strcmp(p->sname, q->sname) < 0)
340                                         break;
341                                 else
342                                         r = q;
343                         }
344
345                         if (r == NULL)
346                         {                               // Insert at front of list
347                                 p->snext = sy[j];
348                                 sy[j] = p;
349                         }
350                         else
351                         {                               // Insert in middle or append to list
352                                 p->snext = r->snext;
353                                 r->snext = p;
354                         }
355                 }
356         }
357
358         // Link all symbols onto one list again
359         p = NULL;
360
361         for(i=0; i<128; ++i)
362         {
363                 if ((r = sy[i]) != NULL)
364                 {
365                         if (p == NULL)
366                                 q = r;
367                         else
368                                 q->snext = r;
369
370                         while (q->snext != NULL)
371                                 q = q->snext;
372
373                         if (p == NULL)
374                                 p = r;
375                 }
376         }
377
378         eject();
379         strcpy(subttl, "Symbol Table");
380
381         while (p != NULL)
382         {
383                 for(i=0; i<4; ++i)
384                 {
385                         colptr[i] = p;
386
387                         for(j=0; j<colhei; ++j)
388                         {
389                                 if (p == NULL)
390                                         break;
391                                 else
392                                         p = p->snext;
393                         }
394                 }
395
396                 for(i=0; i<colhei; ++i)
397                 {
398                         *ln = EOS;
399
400                         if (colptr[0] == NULL)
401                                 break;
402
403                         for(j=0; j<4; ++j)
404                         {
405                                 if ((q = colptr[j]) == NULL)
406                                         break;
407
408                                 colptr[j] = q->snext;
409                                 w = q->sattr;
410                                 ww = q->sattre;
411                                 // Pick a tag:
412                                 // c    common
413                                 // x    external reference
414                                 // g    global (export)
415                                 // space        nothing special
416                                 c1 = SPACE;
417                                 c = SPACE;
418
419                                 if (w & COMMON)
420                                         c = 'c';
421                                 else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
422                                         c = 'x';
423                                 else if (w & GLOBAL)
424                                         c = 'g';
425
426                                 c1 = tdb_text[w & TDB];
427
428                                 if (c == 'x')
429                                         strcpy(ln2, "external");
430                                 else
431                                 {
432                                         sprintf(ln2, "%08X", q->svalue);
433                                         uc_string(ln2);
434                                 }
435
436                                 sprintf(ln1, "  %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);
437                                 strcat(ln, ln1);
438                         }
439
440                         ship_ln(ln);
441                 }
442
443                 eject();
444         }
445
446         return 0;
447 }