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
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
21 // Tags for marking symbol spaces
27 static char tdb_text[8] = {
28 'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE
33 // Initialize Symbol Table
39 for(i=0; i<NBUCKETS; ++i) // Initialise symbol hash table
42 curenv = 1; // Init local symbol enviroment
43 sorder = NULL; // Init symbol-reference list
45 sdecl = NULL; // Init symbol-decl list
51 // Allocate and Return Pointer to a Copy of a String
53 char * nstring(char * str)
73 // Hash the Print Name and Enviroment Number
75 int syhash(char * name, int envno)
77 int sum, k; // Hash calculation
80 for(sum=envno; *name; ++name)
88 return sum & (NBUCKETS - 1);
93 // Make a new symbol of type `type' in enviroment `envno'
95 SYM * newsym(char * name, int type, int envno)
97 int hash; // Symbol hash value
98 SYM * sy; // Pointer to symbol
100 // Allocate the symbol
101 sy = (SYM *)amem((long)(sizeof(SYM)));
105 printf("SYMALLOC ERROR (%s)\n", name);
109 sy->sname = nstring(name);
111 // Fill-in the symbol
112 sy->stype = (BYTE)type;
113 sy->senv = (WORD)envno;
117 sy->sattre = RISCSYM;
123 // Install symbol in symbol table
124 hash = syhash(name, envno);
125 sy->snext = sytab[hash];
128 // Append symbol to symbol-order list
130 sorder = sy; // Add first symbol
132 sordtail->sorder = sy; // Or append to tail of list
137 return sy; // Return pointer to symbol
142 // Lookup the symbol `name', of the specified type, with the specified
145 SYM * lookup(char * name, int type, int envno)
147 SYM * sy; // Symbol record pointer
148 int k, sum; // Hash bucket calculation
149 char * s; // String pointer
151 // Pick a hash-bucket (SAME algorithm as syhash())
163 sy = sytab[sum & (NBUCKETS-1)];
165 // Do linear-search for symbol in bucket
168 if (sy->stype == type && // Type, envno and name must match
170 *name == *sy->sname && // Fast check for first character
171 !strcmp(name, sy->sname))
177 return sy; // Return NULL or matching symbol
182 // Put symbol on "order-of-declaration" list of symbols
184 void sym_decl(SYM * sym)
186 if (sym->sattr & SDECLLIST)
187 return; // Already on list
189 sym->sattr |= SDECLLIST; // Mark "already on list"
192 sdecl = sym; // First on decl-list
194 sdecltail->sdecl = sym; // Add to end of list
196 sym->sdecl = NULL; // Fix up list's tail
202 // Make all referenced, undefined symbols global
208 DEBUG printf("~syg_fix()\n");
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)
214 if (sy->stype == LABEL && sy->senv == 0
215 && ((sy->sattr & (REFERENCED|DEFINED)) == REFERENCED))
224 // Convert string to uppercase
226 int uc_string(char * s)
230 if (*s >= 'a' && *s <= 'z')
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
243 int sy_assign(char * buf, char *(*constr)())
253 // Append all symbols not appearing on the .sdecl list to the end of
255 for(sy=sorder; sy!=NULL; sy=sy->sorder)
257 // Essentially the same as 'sym_decl()' above:
258 if (sy->sattr & SDECLLIST)
259 continue; // Already on list
261 sy->sattr |= SDECLLIST; // Mark "on the list"
264 sdecl = sy; // First on decl-list
266 sdecltail->sdecl = sy; // Add to end of list
268 sy->sdecl = NULL; // Fix up list's tail
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)
277 if (sy->sattre & UNDEF_EQUR)
278 continue; // Don't want undefined on our list
280 if (sy->sattre & UNDEF_CC)
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))
289 sy->senv = (WORD)scount++;
292 buf = (*constr)(buf, sy, 1);
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'))
300 sy->senv = (WORD)scount++;
301 if (buf != NULL) buf = (*constr)(buf, sy, 0);
310 // Generate symbol table for listing file
331 colhei = pagelen - 5;
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)));
340 for(i=0; i<NBUCKETS; ++i)
342 for(p=sytab[i]; p!=NULL; p=k)
348 if (p->stype != LABEL)
349 continue; // Ignore non-labels
351 if (p->sattre & UNDEF_EQUR)
354 for(q=sy[j]; q!=NULL; q=q->snext)
356 if (strcmp(p->sname, q->sname) < 0)
363 { // Insert at front of list
368 { // Insert in middle or append to list
375 // Link all symbols onto one list again
380 if ((r = sy[i]) != NULL)
387 while (q->snext != NULL)
396 strcpy(subttl, "Symbol Table");
404 for(j=0; j<colhei; ++j)
413 for(i=0; i<colhei; ++i)
417 if (colptr[0] == NULL)
422 if ((q = colptr[j]) == NULL)
425 colptr[j] = q->snext;
430 // x external reference
432 // space nothing special
438 else if ((w & (DEFINED|GLOBAL)) == GLOBAL)
443 c1 = tdb_text[w & TDB];
446 strcpy(ln2, "external");
449 sprintf(ln2, "%08ux", q->svalue);
453 sprintf(ln1, " %16s %s %c%c%c", q->sname, ln2, (ww & EQUATEDREG) ? 'e' : SPACE, c1, c);