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