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
;
213 symtab_entry_finalize(y
);
218 * Searches for an entry in a binary tree.
220 * @param id Identifier (search key)
222 static symtab_entry
*binary_search(symtab_entry
*p
, const char *id
)
225 while ((p
!= NULL
) && ((r
= strcmp(p
->id
, id
)) != 0)) {
226 p
= (r
< 0) ? p
->left
: p
->right
;
231 /*---------------------------------------------------------------------------*/
233 static symtab_entry
*lookup(symtab
*st
, const char *id
, int recurse
)
237 e
= binary_search(st
->root
, id
);
238 if (e
!= NULL
) { return e
; }
240 } while (recurse
&& st
);
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
);
281 /* Duplicate symbol. */
282 // printf("error: symtab_enter(): `%s' already exists\n", id);
285 // printf("symtab_enter(): '%s' @ %.8X\n", id, st);
286 /* Allocate new entry */
287 e
= (symtab_entry
*)malloc(sizeof(symtab_entry
));
290 e
->id
= (char *)malloc(strlen(id
)+1);
299 e
->struc
.size
= NULL
;
300 e
->struc
.fields
= NULL
;
301 e
->field
.offset
= NULL
;
302 e
->field
.size
= NULL
;
307 /* Put it into symbol table */
308 if (st
->root
== NULL
) {
309 st
->root
= e
; /* This is the root element */
312 /* Insert entry in binary tree */
313 binary_insert(st
->root
, e
);
316 /* Return the newly created symbol table entry */
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 */
335 case CONSTANT_SYMBOL
:
336 astnode_finalize(e
->def
);
340 astnode_finalize(e
->def
);
346 /* Free list of in-order field identifiers */
347 for (list
= e
->struc
.fields
; list
!= NULL
; list
= next
) {
351 symtab_finalize(e
->symtab
);
352 astnode_finalize(e
->struc
.size
);
356 symtab_finalize(e
->symtab
);
360 astnode_finalize(e
->def
);
361 astnode_finalize(e
->field
.offset
);
362 astnode_finalize(e
->field
.size
);
372 /* Common finalizing */
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
);
400 /*---------------------------------------------------------------------------*/
403 * Gets top of symbol table stack.
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
));
419 st
->parent
= symtab_tos();
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.
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();
463 symtab_entry
*e
= binary_min(st
->root
);
465 if ((type
== ANY_SYMBOL
) || (e
->type
== type
)) {
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
)
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)
498 for (i=0; i<n; i++) {
506 static void symtab_entry_print_recursive(symtab_entry
*e
, int level
)
508 if (e
== NULL
) { return; }
510 symtab_entry_print_recursive(e
->left
, level
+1);
511 printf("%s\n", e
->id
);
512 symtab_entry_print_recursive(e
->right
, level
+1);
520 symtab
*st
= symtab_tos();
521 symtab_entry_print_recursive(st
->root
, 0);
524 /*---------------------------------------------------------------------------*/
527 * Gets the number of entries in the symbol table.
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();
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
);
548 if ((type
== ANY_SYMBOL
) || (e
->type
== type
)) {
550 list
->idents
[i
] = (char *)malloc(strlen(e
->id
)+1);
551 if (list
->idents
[i
] != NULL
) {
552 strcpy(list
->idents
[i
], e
->id
);
559 /* Return the number of entries listed */
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
574 * If flag is zero it is ignored.
576 int symtab_list_flag(int flag
, symbol_ident_list
*list
)
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
)
594 * Finalizes a list of identifiers.
596 void symtab_list_finalize(symbol_ident_list
*list
)
599 for (i
=0; i
<list
->size
; i
++) {
600 SAFE_FREE(list
->idents
[i
]);
602 SAFE_FREE(list
->idents
);