demangle.c revision 1b9cfd6ad305ad909e8ff17139111a7c78f01464
1#if HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#if HAVE_LIBIBERTY 6 7#include <string.h> 8#include <stdlib.h> 9#include <stdio.h> 10 11#include "options.h" 12#include "output.h" 13#include "demangle.h" 14 15/*****************************************************************************/ 16 17/* 18 The string dictionary code done by Morten Eriksen <mortene@sim.no>. 19 20 FIXME: since this is a generic string dictionary, it should perhaps 21 be cleaned up a bit, "object-ified" and placed in its own .c + .h 22 pair of files? 19990702 mortene. 23*/ 24 25struct dict_entry 26{ 27 unsigned int key; 28 const char * mangled, * demangled; 29 struct dict_entry * next; 30}; 31 32#define DICTTABLESIZE 997 /* Semi-randomly selected prime number. */ 33static struct dict_entry * dict_buckets[DICTTABLESIZE]; 34static int dict_initialized = 0; 35 36static void dict_init(void); 37static void dict_clear(void); 38static void dict_enter(const char * mangled, const char * demangled); 39static const char * dict_find_entry(const char * mangled); 40static unsigned int dict_hash_string(const char * s); 41 42 43static void dict_init(void) 44{ 45 int i; 46 /* FIXME: is this necessary? Check with ANSI C spec. 19990702 mortene. */ 47 for (i = 0; i < DICTTABLESIZE; i++) dict_buckets[i] = NULL; 48 dict_initialized = 1; 49} 50 51static void dict_clear(void) 52{ 53 int i; 54 struct dict_entry * entry, * nextentry; 55 56 for (i = 0; i < DICTTABLESIZE; i++) { 57 for (entry = dict_buckets[i]; entry != NULL; entry = nextentry) { 58 nextentry = entry->next; 59 free((void *)(entry->mangled)); 60 if (entry->mangled != entry->demangled) 61 free((void *)(entry->demangled)); 62 free(entry); 63 } 64 dict_buckets[i] = NULL; 65 } 66} 67 68static void dict_enter(const char * mangled, const char * demangled) 69{ 70 struct dict_entry * entry, * newentry; 71 unsigned int key = dict_hash_string(mangled); 72 73 newentry = malloc(sizeof(struct dict_entry)); 74 if (!newentry) { 75 perror("malloc"); 76 return; 77 } 78 79 newentry->key = key; 80 newentry->mangled = mangled; 81 newentry->demangled = demangled; 82 newentry->next = NULL; 83 84 entry = dict_buckets[key % DICTTABLESIZE]; 85 while (entry && entry->next) entry = entry->next; 86 87 if (entry) entry->next = newentry; 88 else dict_buckets[key % DICTTABLESIZE] = newentry; 89 90 if (opt_d > 2) 91 output_line(0, "new dict entry: '%s' -> '%s'\n", mangled, demangled); 92} 93 94static const char * dict_find_entry(const char * mangled) 95{ 96 unsigned int key = dict_hash_string(mangled); 97 struct dict_entry * entry = dict_buckets[key % DICTTABLESIZE]; 98 while (entry) { 99 if ((entry->key == key) && (strcmp(entry->mangled, mangled) == 0)) break; 100 entry = entry->next; 101 } 102 return entry ? entry->demangled : NULL; 103} 104 105static unsigned int dict_hash_string(const char * s) 106{ 107 unsigned int total = 0, shift = 0; 108 109 while (*s) { 110 total = total ^ ((*s) << shift); 111 shift += 5; 112 if (shift > 24) shift -= 24; 113 s++; 114 } 115 return total; 116} 117 118#undef DICTTABLESIZE 119 120/*****************************************************************************/ 121 122const char * my_demangle(const char * function_name) 123{ 124 const char * tmp, * fn_copy; 125 126 if (!dict_initialized) { 127 dict_init(); 128 atexit(dict_clear); 129 } 130 131 tmp = dict_find_entry(function_name); 132 if (!tmp) { 133 fn_copy = strdup(function_name); 134 tmp = cplus_demangle(function_name+strspn(function_name, "_"), DMGL_ANSI | DMGL_PARAMS); 135 if (!tmp) tmp = fn_copy; 136 if (tmp) dict_enter(fn_copy, tmp); 137 } 138 return tmp; 139} 140 141#endif 142