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