2 * $Id: symtab.c,v 1.7 2007/11/11 22:35:22 khansen Exp $
4 * Revision 1.7 2007/11/11 22:35:22 khansen
7 * Revision 1.6 2007/08/09 20:33:57 khansen
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
19 * Revision 1.2 2004/12/06 04:52:53 kenth
22 * Revision 1.1 2004/06/30 07:55:57 kenth
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
46 * This file contains functions for symbol table management.
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 /*---------------------------------------------------------------------------*/
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
) {
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
) {
91 * Gets the successor of an entry.
93 static symtab_entry
*binary_succ(symtab_entry
*p
)
96 if (p
== NULL
) { return NULL
; }
97 if (p
->right
!= NULL
) { return binary_min(p
->right
); }
99 while ((e
!= NULL
) && (p
== e
->right
)) {
108 * Gets the predecessor of an entry.
110 static symtab_entry
*binary_pred(symtab_entry
*p
)
113 if (p
== NULL
) { return NULL
; }
114 if (p
->left
!= NULL
) { return binary_max(p
->left
); }
116 while ((e
!= NULL
) && (p
== e
->left
)) {
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
);
134 /* Follow left branch */
135 if (p
->left
== NULL
) {
136 p
->left
= e
; /* Entry inserted successfully */
140 binary_insert(p
->left
, e
); /* Call recursively */
144 /* Follow right branch */
145 if (p
->right
== NULL
) {
146 p
->right
= e
; /* Entry inserted successfully */
150 binary_insert(p
->right
, e
); /* Call recursively */
154 /* Symbol already present */
159 * Deletes an entry from a binary tree.
161 * @param z Entry to delete
163 static void binary_delete(symtab
*st
, symtab_entry
*z
)
168 if ((st
== NULL
) || (z
== NULL
)) { return; }
170 if ((z
->left
== NULL
) || (z
->right
== NULL
)) {
177 if (y
->left
!= NULL
) {
192 else if (y
== p
->left
) {
200 symtab_finalize(z
->symtab
);
202 z
->id
= (char *)malloc(strlen(y
->id
)+1);
204 strcpy(z
->id
, y
->id
);
208 z
->ref_count
= y
->ref_count
;
210 z
->symtab
= y
->symtab
;
215 symtab_entry_finalize(y
);
220 * Searches for an entry in a binary tree.
222 * @param id Identifier (search key)
224 static symtab_entry
*binary_search(symtab_entry
*p
, const char *id
)
227 while ((p
!= NULL
) && ((r
= strcmp(p
->id
, id
)) != 0)) {
228 p
= (r
< 0) ? p
->left
: p
->right
;
233 /*---------------------------------------------------------------------------*/
235 static symtab_entry
*lookup(symtab
*st
, const char *id
, int recurse
)
239 e
= binary_search(st
->root
, id
);
240 if (e
!= NULL
) { return e
; }
242 } while (recurse
&& st
);
247 * Looks up the specified id in the current symbol table.
249 symtab_entry
*symtab_lookup(const char *id
)
251 return lookup(symtab_tos(), id
, 0);
255 * Looks up the specified id in the current symbol table.
257 symtab_entry
*symtab_lookup_recursive(const char *id
)
259 return lookup(symtab_tos(), id
, 1);
263 * Looks up the specified id in the global symbol table.
265 symtab_entry
*symtab_global_lookup(const char *id
)
267 return lookup(symtab_stack
[0], id
, 0);
271 * Enters something into a symbol table.
272 * @param id Identifier
273 * @param type Type of symbol (*_SYMBOL)
274 * @param def External definition (may be <code>NULL</code>)
275 * @param flags Initial flags
277 symtab_entry
*symtab_enter(const char *id
, symbol_type type
, astnode
*def
, int flags
)
279 symtab
*st
= symtab_tos();
280 /* See if this id already exists */
281 symtab_entry
*e
= symtab_lookup(id
);
283 /* Duplicate symbol. */
284 // printf("error: symtab_enter(): `%s' already exists\n", id);
287 // printf("symtab_enter(): '%s' @ %.8X\n", id, st);
288 /* Allocate new entry */
289 e
= (symtab_entry
*)malloc(sizeof(symtab_entry
));
292 e
->id
= (char *)malloc(strlen(id
)+1);
301 e
->struc
.size
= NULL
;
302 e
->struc
.fields
= NULL
;
303 e
->field
.offset
= NULL
;
304 e
->field
.size
= NULL
;
309 /* Put it into symbol table */
310 if (st
->root
== NULL
) {
311 st
->root
= e
; /* This is the root element */
314 /* Insert entry in binary tree */
315 binary_insert(st
->root
, e
);
318 /* Return the newly created symbol table entry */
322 /*---------------------------------------------------------------------------*/
325 * Finalizes a single symbol table entry.
327 static void symtab_entry_finalize(symtab_entry
*e
)
329 ordered_field_list
*list
;
330 ordered_field_list
*next
;
331 // printf("symtab_finalize(): `%s'\n", e->id);
332 /* Special finalizing */
337 case CONSTANT_SYMBOL
:
338 astnode_finalize(e
->def
);
342 astnode_finalize(e
->def
);
348 /* Free list of in-order field identifiers */
349 for (list
= e
->struc
.fields
; list
!= NULL
; list
= next
) {
353 symtab_finalize(e
->symtab
);
354 astnode_finalize(e
->struc
.size
);
358 symtab_finalize(e
->symtab
);
362 astnode_finalize(e
->def
);
363 astnode_finalize(e
->field
.offset
);
364 astnode_finalize(e
->field
.size
);
374 /* Common finalizing */
380 * Finalizes a symbol table entry recursively,
381 * by first finalizing its children before finalizing itself.
383 static void symtab_entry_finalize_recursive(symtab_entry
*e
)
385 if (e
== NULL
) return;
386 symtab_entry_finalize_recursive(e
->left
);
387 symtab_entry_finalize_recursive(e
->right
);
388 symtab_entry_finalize(e
);
392 * Finalizes a symbol table.
393 * @param st The symbol table to finalize
395 void symtab_finalize(symtab
*st
)
397 if (st
== NULL
) return;
398 symtab_entry_finalize_recursive(st
->root
);
402 /*---------------------------------------------------------------------------*/
405 * Gets top of symbol table stack.
409 if (stack_index
== 0) { return NULL
; }
410 return symtab_stack
[stack_index
-1];
414 * Creates a symbol table and pushes it on the symbol table stack.
416 symtab
*symtab_create()
418 symtab
*st
= (symtab
*)malloc(sizeof(symtab
));
421 st
->parent
= symtab_tos();
428 * Pushes a symbol table onto the stack.
430 void symtab_push(symtab
*st
)
432 symtab_stack
[stack_index
++] = st
;
436 * Pops a symbol table from the stack.
440 return symtab_stack
[--stack_index
];
444 * Removes an entry from the symbol table.
445 * The memory associated with the entry is freed.
446 * @param id Identifier of the entry to remove
448 void symtab_remove(const char *id
)
450 symtab
*st
= symtab_tos();
451 symtab_entry
* e
= symtab_lookup(id
);
452 if (e
== NULL
) { return; } /* Nothing to remove */
453 binary_delete(st
, e
);
456 /*---------------------------------------------------------------------------*/
459 * Gets the number of entries of the given type.
461 int symtab_type_count(symbol_type type
)
463 symtab
*st
= symtab_tos();
465 symtab_entry
*e
= binary_min(st
->root
);
467 if ((type
== ANY_SYMBOL
) || (e
->type
== type
)) {
476 * Removes all entries of a given type from the symbol table.
477 * The memory associated with the entries is freed.
478 * @param type Type of symbols to remove
480 void symtab_remove_by_type(symbol_type type
)
483 /* Declare array to hold identifiers */
484 symbol_ident_list list
;
485 /* List the entry identifiers */
486 int count
= symtab_list_type(type
, &list
);
487 /* Remove the entries one by one */
488 for (i
=0; i
<count
; i
++) {
489 symtab_remove(list
.idents
[i
]);
491 /* Finalize the array of identifiers */
492 symtab_list_finalize(&list
);
495 /*---------------------------------------------------------------------------*/
497 static void indent(int n)
500 for (i=0; i<n; i++) {
508 static void symtab_entry_print_recursive(symtab_entry
*e
, int level
)
510 if (e
== NULL
) { return; }
512 symtab_entry_print_recursive(e
->left
, level
+1);
513 printf("%s\n", e
->id
);
514 symtab_entry_print_recursive(e
->right
, level
+1);
522 symtab
*st
= symtab_tos();
523 symtab_entry_print_recursive(st
->root
, 0);
526 /*---------------------------------------------------------------------------*/
529 * Gets the number of entries in the symbol table.
533 return symtab_type_count(ANY_SYMBOL
);
537 * Lists the entries in a symbol table that are of a certain type.
538 * @param type The symbol type (*_SYMBOL)
539 * @param list List which will receive the array of identifiers
541 int symtab_list_type(symbol_type type
, symbol_ident_list
*list
)
543 symtab
*st
= symtab_tos();
545 list
->size
= symtab_type_count(type
);
546 list
->idents
= (char **)malloc(list
->size
* sizeof(char *) );
547 if (list
->idents
!= NULL
) {
548 symtab_entry
*e
= binary_min(st
->root
);
550 if ((type
== ANY_SYMBOL
) || (e
->type
== type
)) {
552 list
->idents
[i
] = (char *)malloc(strlen(e
->id
)+1);
553 if (list
->idents
[i
] != NULL
) {
554 strcpy(list
->idents
[i
], e
->id
);
561 /* Return the number of entries listed */
566 * Lists all identifiers in the symbol table.
568 int symtab_list(symbol_ident_list
*list
)
570 return symtab_list_type(ANY_SYMBOL
, list
);
574 * Lists all identifiers in the symbol table which has ONE OR MORE of the
576 * If flag is zero it is ignored.
578 int symtab_list_flag(int flag
, symbol_ident_list
*list
)
585 * Lists all identifiers in the symbol table of a given type which has
586 * ONE OR MORE of the given flags set.
587 * If flag is zero it is ignored.
589 int symtab_list_type_flag(symbol_type type
, int flag
, symbol_ident_list
*list
)
596 * Finalizes a list of identifiers.
598 void symtab_list_finalize(symbol_ident_list
*list
)
601 for (i
=0; i
<list
->size
; i
++) {
602 SAFE_FREE(list
->idents
[i
]);
604 SAFE_FREE(list
->idents
);