allow extrn symbols to be defined by the unit itself (part II)
[xorcyst.git] / symtab.c
blobd1898588d7f74c4289c6979768d88faff96f79fb
1 /*
2 * $Id: symtab.c,v 1.7 2007/11/11 22:35:22 khansen Exp $
3 * $Log: symtab.c,v $
4 * Revision 1.7 2007/11/11 22:35:22 khansen
5 * compile on mac
7 * Revision 1.6 2007/08/09 20:33:57 khansen
8 * progress
10 * Revision 1.5 2007/08/08 22:40:43 khansen
11 * recursive symbol table lookup
13 * Revision 1.4 2007/07/22 13:33:26 khansen
14 * convert tabs to whitespaces
16 * Revision 1.3 2004/12/14 01:50:05 kenth
17 * xorcyst 1.3.0
19 * Revision 1.2 2004/12/06 04:52:53 kenth
20 * xorcyst 1.1.0
22 * Revision 1.1 2004/06/30 07:55:57 kenth
23 * Initial revision
27 /**
28 * (C) 2004 Kent Hansen
30 * The XORcyst is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
35 * The XORcyst is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with The XORcyst; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 /**
46 * This file contains functions for symbol table management.
49 #include "symtab.h"
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdio.h>
54 #define SAFE_FREE(a) if (a) { free(a); a = NULL; }
56 /* Stack of symbol tables */
57 static symtab *symtab_stack[32] = { NULL };
58 static int stack_index = 0;
60 static void symtab_entry_finalize(symtab_entry *);
62 /*---------------------------------------------------------------------------*/
64 /**
65 * Gets the entry in the tree with minimum key.
67 static symtab_entry *binary_min(symtab_entry *p)
69 if (p == NULL) { return NULL; }
70 while (p->left != NULL) {
71 p = p->left;
73 return p;
76 #if 0
77 /**
78 * Gets the entry in the tree with maximum key.
80 static symtab_entry *binary_max(symtab_entry *p)
82 if (p == NULL) { return NULL; }
83 while (p->right != NULL) {
84 p = p->right;
86 return p;
88 #endif
90 /**
91 * Gets the successor of an entry.
93 static symtab_entry *binary_succ(symtab_entry *p)
95 symtab_entry *e;
96 if (p == NULL) { return NULL; }
97 if (p->right != NULL) { return binary_min(p->right); }
98 e = p->parent;
99 while ((e != NULL) && (p == e->right)) {
100 p = e;
101 e = e->parent;
103 return e;
106 #if 0
108 * Gets the predecessor of an entry.
110 static symtab_entry *binary_pred(symtab_entry *p)
112 symtab_entry *e;
113 if (p == NULL) { return NULL; }
114 if (p->left != NULL) { return binary_max(p->left); }
115 e = p->parent;
116 while ((e != NULL) && (p == e->left)) {
117 p = e;
118 e = e->parent;
120 return e;
122 #endif
125 * Inserts a new entry in a binary tree.
126 * It's implemented recursively although that's a bad thing.
127 * @param p The root of the tree
128 * @param e A new entry to be inserted
130 static void binary_insert(symtab_entry *p, symtab_entry *e)
132 int r = strcmp(p->id, e->id);
133 if (r < 0) {
134 /* Follow left branch */
135 if (p->left == NULL) {
136 p->left = e; /* Entry inserted successfully */
137 e->parent = p;
139 else {
140 binary_insert(p->left, e); /* Call recursively */
143 else if (r > 0) {
144 /* Follow right branch */
145 if (p->right == NULL) {
146 p->right = e; /* Entry inserted successfully */
147 e->parent = p;
149 else {
150 binary_insert(p->right, e); /* Call recursively */
153 else {
154 /* Symbol already present */
159 * Deletes an entry from a binary tree.
160 * @param p Root node
161 * @param z Entry to delete
163 static void binary_delete(symtab *st, symtab_entry *z)
165 symtab_entry *y;
166 symtab_entry *x;
167 symtab_entry *p;
168 if ((st == NULL) || (z == NULL)) { return; }
170 if ((z->left == NULL) || (z->right == NULL)) {
171 y = z;
173 else {
174 y = binary_succ(z);
177 if (y->left != NULL) {
178 x = y->left;
180 else {
181 x = y->right;
184 p = y->parent;
185 if (x != NULL) {
186 x->parent = p;
189 if (p == NULL) {
190 st->root = x;
192 else if (y == p->left) {
193 p->left = x;
195 else {
196 p->right = x;
199 if (y != z) {
200 symtab_finalize(z->symtab);
201 SAFE_FREE(z->id);
202 z->id = (char *)malloc(strlen(y->id)+1);
203 if (z->id != NULL) {
204 strcpy(z->id, y->id);
206 z->type = y->type;
207 z->flags = y->flags;
208 z->ref_count = y->ref_count;
209 z->def = y->def;
210 z->symtab = y->symtab;
211 z->tag = y->tag;
212 } else {
213 symtab_entry_finalize(y);
218 * Searches for an entry in a binary tree.
219 * @param p Root node
220 * @param id Identifier (search key)
222 static symtab_entry *binary_search(symtab_entry *p, const char *id)
224 int r;
225 while ((p != NULL) && ((r = strcmp(p->id, id)) != 0)) {
226 p = (r < 0) ? p->left : p->right;
228 return p;
231 /*---------------------------------------------------------------------------*/
233 static symtab_entry *lookup(symtab *st, const char *id, int recurse)
235 symtab_entry *e;
236 do {
237 e = binary_search(st->root, id);
238 if (e != NULL) { return e; }
239 st = st->parent;
240 } while (recurse && st);
241 return NULL;
245 * Looks up the specified id in the current symbol table.
247 symtab_entry *symtab_lookup(const char *id)
249 return lookup(symtab_tos(), id, 0);
253 * Looks up the specified id in the current symbol table.
255 symtab_entry *symtab_lookup_recursive(const char *id)
257 return lookup(symtab_tos(), id, 1);
261 * Looks up the specified id in the global symbol table.
263 symtab_entry *symtab_global_lookup(const char *id)
265 return lookup(symtab_stack[0], id, 0);
269 * Enters something into a symbol table.
270 * @param id Identifier
271 * @param type Type of symbol (*_SYMBOL)
272 * @param def External definition (may be <code>NULL</code>)
273 * @param flags Initial flags
275 symtab_entry *symtab_enter(const char *id, symbol_type type, astnode *def, int flags)
277 symtab *st = symtab_tos();
278 /* See if this id already exists */
279 symtab_entry *e = symtab_lookup(id);
280 if (e != NULL) {
281 /* Duplicate symbol. */
282 // printf("error: symtab_enter(): `%s' already exists\n", id);
283 return NULL;
285 // printf("symtab_enter(): '%s' @ %.8X\n", id, st);
286 /* Allocate new entry */
287 e = (symtab_entry *)malloc(sizeof(symtab_entry));
288 if (e != NULL) {
289 /* Set its fields */
290 e->id = (char *)malloc(strlen(id)+1);
291 if (e->id != NULL) {
292 strcpy(e->id, id);
294 e->type = type;
295 e->flags = flags;
296 e->ref_count = 0;
297 e->def = def;
298 /* Zap! */
299 e->struc.size = NULL;
300 e->struc.fields = NULL;
301 e->field.offset = NULL;
302 e->field.size = NULL;
303 e->left = NULL;
304 e->right = NULL;
305 e->parent = NULL;
306 e->symtab = NULL;
307 /* Put it into symbol table */
308 if (st->root == NULL) {
309 st->root = e; /* This is the root element */
311 else {
312 /* Insert entry in binary tree */
313 binary_insert(st->root, e);
316 /* Return the newly created symbol table entry */
317 return e;
320 /*---------------------------------------------------------------------------*/
323 * Finalizes a single symbol table entry.
325 static void symtab_entry_finalize(symtab_entry *e)
327 ordered_field_list *list;
328 ordered_field_list *next;
329 // printf("symtab_finalize(): `%s'\n", e->id);
330 /* Special finalizing */
331 switch (e->type) {
332 case LABEL_SYMBOL:
333 break;
335 case CONSTANT_SYMBOL:
336 astnode_finalize(e->def);
337 break;
339 case MACRO_SYMBOL:
340 astnode_finalize(e->def);
341 break;
343 case STRUC_SYMBOL:
344 case UNION_SYMBOL:
345 case RECORD_SYMBOL:
346 /* Free list of in-order field identifiers */
347 for (list = e->struc.fields; list != NULL; list = next) {
348 next = list->next;
349 free(list);
351 symtab_finalize(e->symtab);
352 astnode_finalize(e->struc.size);
353 break;
355 case ENUM_SYMBOL:
356 symtab_finalize(e->symtab);
357 break;
359 case VAR_SYMBOL:
360 astnode_finalize(e->def);
361 astnode_finalize(e->field.offset);
362 astnode_finalize(e->field.size);
363 break;
365 case PROC_SYMBOL:
366 break;
368 default:
369 /* Nada */
370 break;
372 /* Common finalizing */
373 SAFE_FREE(e->id);
374 SAFE_FREE(e);
378 * Finalizes a symbol table entry recursively,
379 * by first finalizing its children before finalizing itself.
381 static void symtab_entry_finalize_recursive(symtab_entry *e)
383 if (e == NULL) return;
384 symtab_entry_finalize_recursive(e->left);
385 symtab_entry_finalize_recursive(e->right);
386 symtab_entry_finalize(e);
390 * Finalizes a symbol table.
391 * @param st The symbol table to finalize
393 void symtab_finalize(symtab *st)
395 if (st == NULL) return;
396 symtab_entry_finalize_recursive(st->root);
397 SAFE_FREE(st);
400 /*---------------------------------------------------------------------------*/
403 * Gets top of symbol table stack.
405 symtab *symtab_tos()
407 if (stack_index == 0) { return NULL; }
408 return symtab_stack[stack_index-1];
412 * Creates a symbol table and pushes it on the symbol table stack.
414 symtab *symtab_create()
416 symtab *st = (symtab *)malloc(sizeof(symtab));
417 if (st != NULL) {
418 st->root = NULL;
419 st->parent = symtab_tos();
420 symtab_push(st);
422 return st;
426 * Pushes a symbol table onto the stack.
428 void symtab_push(symtab *st)
430 symtab_stack[stack_index++] = st;
434 * Pops a symbol table from the stack.
436 symtab *symtab_pop()
438 return symtab_stack[--stack_index];
442 * Removes an entry from the symbol table.
443 * The memory associated with the entry is freed.
444 * @param id Identifier of the entry to remove
446 void symtab_remove(const char *id)
448 symtab *st = symtab_tos();
449 symtab_entry * e = symtab_lookup(id);
450 if (e == NULL) { return; } /* Nothing to remove */
451 binary_delete(st, e);
454 /*---------------------------------------------------------------------------*/
457 * Gets the number of entries of the given type.
459 int symtab_type_count(symbol_type type)
461 symtab *st = symtab_tos();
462 int count = 0;
463 symtab_entry *e = binary_min(st->root);
464 while (e != NULL) {
465 if ((type == ANY_SYMBOL) || (e->type == type)) {
466 count++;
468 e = binary_succ(e);
470 return count;
474 * Removes all entries of a given type from the symbol table.
475 * The memory associated with the entries is freed.
476 * @param type Type of symbols to remove
478 void symtab_remove_by_type(symbol_type type)
480 int i;
481 /* Declare array to hold identifiers */
482 symbol_ident_list list;
483 /* List the entry identifiers */
484 int count = symtab_list_type(type, &list);
485 /* Remove the entries one by one */
486 for (i=0; i<count; i++) {
487 symtab_remove(list.idents[i]);
489 /* Finalize the array of identifiers */
490 symtab_list_finalize(&list);
493 /*---------------------------------------------------------------------------*/
495 static void indent(int n)
497 int i;
498 for (i=0; i<n; i++) {
499 printf(" ");
506 static void symtab_entry_print_recursive(symtab_entry *e, int level)
508 if (e == NULL) { return; }
509 //indent(level*2);
510 symtab_entry_print_recursive(e->left, level+1);
511 printf("%s\n", e->id);
512 symtab_entry_print_recursive(e->right, level+1);
518 void symtab_print()
520 symtab *st = symtab_tos();
521 symtab_entry_print_recursive(st->root, 0);
524 /*---------------------------------------------------------------------------*/
527 * Gets the number of entries in the symbol table.
529 int symtab_size()
531 return symtab_type_count(ANY_SYMBOL);
535 * Lists the entries in a symbol table that are of a certain type.
536 * @param type The symbol type (*_SYMBOL)
537 * @param list List which will receive the array of identifiers
539 int symtab_list_type(symbol_type type, symbol_ident_list *list)
541 symtab *st = symtab_tos();
542 int i = 0;
543 list->size = symtab_type_count(type);
544 list->idents = (char **)malloc(list->size * sizeof(char *) );
545 if (list->idents != NULL) {
546 symtab_entry *e = binary_min(st->root);
547 while (e != NULL) {
548 if ((type == ANY_SYMBOL) || (e->type == type)) {
549 /* Add to list */
550 list->idents[i] = (char *)malloc(strlen(e->id)+1);
551 if (list->idents[i] != NULL) {
552 strcpy(list->idents[i], e->id);
553 i++;
556 e = binary_succ(e);
559 /* Return the number of entries listed */
560 return i;
564 * Lists all identifiers in the symbol table.
566 int symtab_list(symbol_ident_list *list)
568 return symtab_list_type(ANY_SYMBOL, list);
572 * Lists all identifiers in the symbol table which has ONE OR MORE of the
573 * given flags set.
574 * If flag is zero it is ignored.
576 int symtab_list_flag(int flag, symbol_ident_list *list)
578 // TODO
579 return 0;
583 * Lists all identifiers in the symbol table of a given type which has
584 * ONE OR MORE of the given flags set.
585 * If flag is zero it is ignored.
587 int symtab_list_type_flag(symbol_type type, int flag, symbol_ident_list *list)
589 // TODO
590 return 0;
594 * Finalizes a list of identifiers.
596 void symtab_list_finalize(symbol_ident_list *list)
598 int i;
599 for (i=0; i<list->size; i++) {
600 SAFE_FREE(list->idents[i]);
602 SAFE_FREE(list->idents);