rdwarf 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +28 -0
- data/README.md +39 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/ext/rdwarf/depend +5 -0
- data/ext/rdwarf/extconf.rb +29 -0
- data/ext/rdwarf/libdwarf/CHANGES +102 -0
- data/ext/rdwarf/libdwarf/CODINGSTYLE +71 -0
- data/ext/rdwarf/libdwarf/COPYING +28 -0
- data/ext/rdwarf/libdwarf/ChangeLog +619 -0
- data/ext/rdwarf/libdwarf/ChangeLog2006 +835 -0
- data/ext/rdwarf/libdwarf/ChangeLog2007 +217 -0
- data/ext/rdwarf/libdwarf/ChangeLog2008 +263 -0
- data/ext/rdwarf/libdwarf/ChangeLog2009 +348 -0
- data/ext/rdwarf/libdwarf/ChangeLog2010 +175 -0
- data/ext/rdwarf/libdwarf/ChangeLog2011 +297 -0
- data/ext/rdwarf/libdwarf/ChangeLog2012 +131 -0
- data/ext/rdwarf/libdwarf/ChangeLog2013 +238 -0
- data/ext/rdwarf/libdwarf/ChangeLog2014 +399 -0
- data/ext/rdwarf/libdwarf/LGPL.txt +504 -0
- data/ext/rdwarf/libdwarf/LIBDWARFCOPYRIGHT +40 -0
- data/ext/rdwarf/libdwarf/Makefile.in +220 -0
- data/ext/rdwarf/libdwarf/NEWS +535 -0
- data/ext/rdwarf/libdwarf/README +235 -0
- data/ext/rdwarf/libdwarf/checkexamples.c +1179 -0
- data/ext/rdwarf/libdwarf/cmplrs/dwarf_addr_finder.h +55 -0
- data/ext/rdwarf/libdwarf/common.c +62 -0
- data/ext/rdwarf/libdwarf/common.h +38 -0
- data/ext/rdwarf/libdwarf/config.h.in +146 -0
- data/ext/rdwarf/libdwarf/configure +5581 -0
- data/ext/rdwarf/libdwarf/configure.in +167 -0
- data/ext/rdwarf/libdwarf/dw-linetableheader.txt +39 -0
- data/ext/rdwarf/libdwarf/dwarf.h +1342 -0
- data/ext/rdwarf/libdwarf/dwarf_abbrev.c +291 -0
- data/ext/rdwarf/libdwarf/dwarf_abbrev.h +45 -0
- data/ext/rdwarf/libdwarf/dwarf_addr_finder.c +676 -0
- data/ext/rdwarf/libdwarf/dwarf_alloc.c +685 -0
- data/ext/rdwarf/libdwarf/dwarf_alloc.h +38 -0
- data/ext/rdwarf/libdwarf/dwarf_arange.c +595 -0
- data/ext/rdwarf/libdwarf/dwarf_arange.h +62 -0
- data/ext/rdwarf/libdwarf/dwarf_base_types.h +157 -0
- data/ext/rdwarf/libdwarf/dwarf_die_deliv.c +1802 -0
- data/ext/rdwarf/libdwarf/dwarf_die_deliv.h +46 -0
- data/ext/rdwarf/libdwarf/dwarf_elf_access.c +1348 -0
- data/ext/rdwarf/libdwarf/dwarf_elf_access.h +46 -0
- data/ext/rdwarf/libdwarf/dwarf_error.c +492 -0
- data/ext/rdwarf/libdwarf/dwarf_error.h +53 -0
- data/ext/rdwarf/libdwarf/dwarf_form.c +1302 -0
- data/ext/rdwarf/libdwarf/dwarf_frame.c +2454 -0
- data/ext/rdwarf/libdwarf/dwarf_frame.h +418 -0
- data/ext/rdwarf/libdwarf/dwarf_frame2.c +1533 -0
- data/ext/rdwarf/libdwarf/dwarf_frame3.c +282 -0
- data/ext/rdwarf/libdwarf/dwarf_funcs.c +123 -0
- data/ext/rdwarf/libdwarf/dwarf_funcs.h +33 -0
- data/ext/rdwarf/libdwarf/dwarf_gdbindex.c +520 -0
- data/ext/rdwarf/libdwarf/dwarf_gdbindex.h +97 -0
- data/ext/rdwarf/libdwarf/dwarf_global.c +612 -0
- data/ext/rdwarf/libdwarf/dwarf_global.h +117 -0
- data/ext/rdwarf/libdwarf/dwarf_harmless.c +228 -0
- data/ext/rdwarf/libdwarf/dwarf_harmless.h +31 -0
- data/ext/rdwarf/libdwarf/dwarf_incl.h +61 -0
- data/ext/rdwarf/libdwarf/dwarf_init_finish.c +1263 -0
- data/ext/rdwarf/libdwarf/dwarf_leb.c +159 -0
- data/ext/rdwarf/libdwarf/dwarf_line.c +1822 -0
- data/ext/rdwarf/libdwarf/dwarf_line.h +446 -0
- data/ext/rdwarf/libdwarf/dwarf_line2.c +98 -0
- data/ext/rdwarf/libdwarf/dwarf_line_table_reader_common.c +1583 -0
- data/ext/rdwarf/libdwarf/dwarf_loc.c +1525 -0
- data/ext/rdwarf/libdwarf/dwarf_loc.h +149 -0
- data/ext/rdwarf/libdwarf/dwarf_loc2.c +833 -0
- data/ext/rdwarf/libdwarf/dwarf_macro.c +479 -0
- data/ext/rdwarf/libdwarf/dwarf_macro.h +35 -0
- data/ext/rdwarf/libdwarf/dwarf_opaque.h +778 -0
- data/ext/rdwarf/libdwarf/dwarf_original_elf_init.c +219 -0
- data/ext/rdwarf/libdwarf/dwarf_print_lines.c +631 -0
- data/ext/rdwarf/libdwarf/dwarf_pubtypes.c +132 -0
- data/ext/rdwarf/libdwarf/dwarf_query.c +1594 -0
- data/ext/rdwarf/libdwarf/dwarf_ranges.c +194 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_arm.h +308 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_mips.h +117 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_ppc.h +242 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_ppc64.h +272 -0
- data/ext/rdwarf/libdwarf/dwarf_reloc_x86_64.h +127 -0
- data/ext/rdwarf/libdwarf/dwarf_sort_line.c +665 -0
- data/ext/rdwarf/libdwarf/dwarf_string.c +82 -0
- data/ext/rdwarf/libdwarf/dwarf_stubs.c +38 -0
- data/ext/rdwarf/libdwarf/dwarf_tied.c +423 -0
- data/ext/rdwarf/libdwarf/dwarf_tsearch.h +125 -0
- data/ext/rdwarf/libdwarf/dwarf_tsearchhash.c +675 -0
- data/ext/rdwarf/libdwarf/dwarf_types.c +121 -0
- data/ext/rdwarf/libdwarf/dwarf_types.h +32 -0
- data/ext/rdwarf/libdwarf/dwarf_util.c +913 -0
- data/ext/rdwarf/libdwarf/dwarf_util.h +324 -0
- data/ext/rdwarf/libdwarf/dwarf_vars.c +125 -0
- data/ext/rdwarf/libdwarf/dwarf_vars.h +29 -0
- data/ext/rdwarf/libdwarf/dwarf_weaks.c +123 -0
- data/ext/rdwarf/libdwarf/dwarf_weaks.h +29 -0
- data/ext/rdwarf/libdwarf/dwarf_xu_index.c +579 -0
- data/ext/rdwarf/libdwarf/dwarf_xu_index.h +68 -0
- data/ext/rdwarf/libdwarf/dwgetopt.c +181 -0
- data/ext/rdwarf/libdwarf/dwgetopt.h +51 -0
- data/ext/rdwarf/libdwarf/gennames.c +531 -0
- data/ext/rdwarf/libdwarf/install.sh +119 -0
- data/ext/rdwarf/libdwarf/libdwarf.h.in +3746 -0
- data/ext/rdwarf/libdwarf/libdwarf2.1.mm +9805 -0
- data/ext/rdwarf/libdwarf/libdwarf2.1.pdf +0 -0
- data/ext/rdwarf/libdwarf/libdwarf2p.1.mm +2807 -0
- data/ext/rdwarf/libdwarf/libdwarf2p.1.pdf +0 -0
- data/ext/rdwarf/libdwarf/libdwarfdefs.h +81 -0
- data/ext/rdwarf/libdwarf/malloc_check.c +327 -0
- data/ext/rdwarf/libdwarf/malloc_check.h +52 -0
- data/ext/rdwarf/libdwarf/mips_extensions.mm +1266 -0
- data/ext/rdwarf/libdwarf/mips_extensions.pdf +0 -0
- data/ext/rdwarf/libdwarf/pro_alloc.c +179 -0
- data/ext/rdwarf/libdwarf/pro_alloc.h +33 -0
- data/ext/rdwarf/libdwarf/pro_arange.c +310 -0
- data/ext/rdwarf/libdwarf/pro_arange.h +51 -0
- data/ext/rdwarf/libdwarf/pro_die.c +431 -0
- data/ext/rdwarf/libdwarf/pro_die.h +59 -0
- data/ext/rdwarf/libdwarf/pro_encode_nm.c +108 -0
- data/ext/rdwarf/libdwarf/pro_encode_nm.h +39 -0
- data/ext/rdwarf/libdwarf/pro_error.c +96 -0
- data/ext/rdwarf/libdwarf/pro_error.h +43 -0
- data/ext/rdwarf/libdwarf/pro_expr.c +575 -0
- data/ext/rdwarf/libdwarf/pro_expr.h +36 -0
- data/ext/rdwarf/libdwarf/pro_finish.c +45 -0
- data/ext/rdwarf/libdwarf/pro_forms.c +1271 -0
- data/ext/rdwarf/libdwarf/pro_frame.c +572 -0
- data/ext/rdwarf/libdwarf/pro_frame.h +120 -0
- data/ext/rdwarf/libdwarf/pro_funcs.c +50 -0
- data/ext/rdwarf/libdwarf/pro_incl.h +91 -0
- data/ext/rdwarf/libdwarf/pro_init.c +327 -0
- data/ext/rdwarf/libdwarf/pro_line.c +373 -0
- data/ext/rdwarf/libdwarf/pro_line.h +112 -0
- data/ext/rdwarf/libdwarf/pro_macinfo.c +457 -0
- data/ext/rdwarf/libdwarf/pro_macinfo.h +31 -0
- data/ext/rdwarf/libdwarf/pro_opaque.h +513 -0
- data/ext/rdwarf/libdwarf/pro_pubnames.c +60 -0
- data/ext/rdwarf/libdwarf/pro_reloc.c +253 -0
- data/ext/rdwarf/libdwarf/pro_reloc.h +38 -0
- data/ext/rdwarf/libdwarf/pro_reloc_stream.c +256 -0
- data/ext/rdwarf/libdwarf/pro_reloc_stream.h +52 -0
- data/ext/rdwarf/libdwarf/pro_reloc_symbolic.c +245 -0
- data/ext/rdwarf/libdwarf/pro_reloc_symbolic.h +45 -0
- data/ext/rdwarf/libdwarf/pro_section.c +2233 -0
- data/ext/rdwarf/libdwarf/pro_section.h +100 -0
- data/ext/rdwarf/libdwarf/pro_types.c +274 -0
- data/ext/rdwarf/libdwarf/pro_types.h +34 -0
- data/ext/rdwarf/libdwarf/pro_util.h +38 -0
- data/ext/rdwarf/libdwarf/pro_vars.c +52 -0
- data/ext/rdwarf/libdwarf/pro_weaks.c +51 -0
- data/ext/rdwarf/rdwarf.c +765 -0
- data/ext/rdwarf/rdwarf.h +52 -0
- data/ext/rdwarf/rdwarf_names_gen.rb +109 -0
- data/lib/rdwarf.rb +181 -0
- data/lib/rdwarf/version.rb +3 -0
- data/rdwarf.gemspec +30 -0
- metadata +251 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
#ifndef DWARF_TSEARCH
|
2
|
+
#define DWARF_TSEARCH
|
3
|
+
/* Copyright (c) 2013, David Anderson
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with
|
7
|
+
or without modification, are permitted provided that the
|
8
|
+
following conditions are met:
|
9
|
+
|
10
|
+
Redistributions of source code must retain the above
|
11
|
+
copyright notice, this list of conditions and the following
|
12
|
+
disclaimer.
|
13
|
+
|
14
|
+
Redistributions in binary form must reproduce the above
|
15
|
+
copyright notice, this list of conditions and the following
|
16
|
+
disclaimer in the documentation and/or other materials
|
17
|
+
provided with the distribution.
|
18
|
+
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
20
|
+
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
21
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
22
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
24
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
25
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
26
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
27
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
28
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
29
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
30
|
+
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
31
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
|
+
|
33
|
+
*/
|
34
|
+
|
35
|
+
|
36
|
+
/* The following interfaces follow tsearch (See the Single
|
37
|
+
Unix Specification) but the implementation is
|
38
|
+
written without reference to the source code
|
39
|
+
of any version of tsearch. Only uses
|
40
|
+
of tsearch were examined, not tsearch source code.
|
41
|
+
|
42
|
+
See http://reality.sgiweb.org/davea/tsearch.html
|
43
|
+
for information about tsearch.
|
44
|
+
|
45
|
+
We are matching the standard functional
|
46
|
+
interface here, but to avoid interfering with
|
47
|
+
libc implementations or code using libc
|
48
|
+
implementations, we change all the names.
|
49
|
+
|
50
|
+
*/
|
51
|
+
|
52
|
+
/* The DW_VISIT values passed back to you through
|
53
|
+
the callback function in dwarf_twalk();
|
54
|
+
*/
|
55
|
+
typedef enum
|
56
|
+
{
|
57
|
+
dwarf_preorder,
|
58
|
+
dwarf_postorder,
|
59
|
+
dwarf_endorder,
|
60
|
+
dwarf_leaf
|
61
|
+
}
|
62
|
+
DW_VISIT;
|
63
|
+
|
64
|
+
/* void * return values are actually
|
65
|
+
void **key so you must dereference these
|
66
|
+
once to get a key you passed in.
|
67
|
+
|
68
|
+
*/
|
69
|
+
|
70
|
+
/* We rename these so there is no conflict with another version
|
71
|
+
of the tsearch sources, such as is used in dwarfdump. */
|
72
|
+
#define dwarf_tsearch _dwarf_tsearch
|
73
|
+
#define dwarf_tfind _dwarf_tfind
|
74
|
+
#define dwarf_tdelete _dwarf_tdelete
|
75
|
+
#define dwarf_twalk _dwarf_twalk
|
76
|
+
#define dwarf_tdestroy _dwarf_tdestroy
|
77
|
+
#define dwarf_tdump _dwarf_tdump
|
78
|
+
#define dwarf_initialize_search_hash _dwarf_initialize_search_hash
|
79
|
+
|
80
|
+
|
81
|
+
void *dwarf_tsearch(const void * /*key*/, void ** /*rootp*/,
|
82
|
+
int (* /*compar*/)(const void *, const void *));
|
83
|
+
|
84
|
+
void *dwarf_tfind(const void * /*key*/, void *const * /*rootp*/,
|
85
|
+
int (* /*compar*/)(const void *, const void *));
|
86
|
+
|
87
|
+
/*
|
88
|
+
dwarf_tdelete() returns NULL if it cannot delete anything
|
89
|
+
or if the tree is now empty (if empty, *rootp
|
90
|
+
is set NULL by dwarf_tdelete()).
|
91
|
+
If the delete succeeds and the tree is non-empty returns
|
92
|
+
a pointer to the parent node of the deleted item,
|
93
|
+
unless the deleted item was at the root, in which
|
94
|
+
case the returned pointer relates to the new root.
|
95
|
+
*/
|
96
|
+
void *dwarf_tdelete(const void * /*key*/, void ** /*rootp*/,
|
97
|
+
int (* /*compar*/)(const void *, const void *));
|
98
|
+
|
99
|
+
void dwarf_twalk(const void * /*root*/,
|
100
|
+
void (* /*action*/)(const void * /*nodep*/,
|
101
|
+
const DW_VISIT /*which*/,
|
102
|
+
const int /*depth*/));
|
103
|
+
|
104
|
+
/* dwarf_tdestroy() cannot set the root pointer NULL, you must do
|
105
|
+
so on return from dwarf_tdestroy(). */
|
106
|
+
void dwarf_tdestroy(void * /*root*/,
|
107
|
+
void (* /*free_node*/)(void * /*nodep*/));
|
108
|
+
|
109
|
+
|
110
|
+
/* Prints a simple tree representation to stdout. For debugging.
|
111
|
+
*/
|
112
|
+
void dwarf_tdump(const void*root,
|
113
|
+
char *(* /*keyprint*/)(const void *),
|
114
|
+
const char *msg);
|
115
|
+
|
116
|
+
/* Returns NULL and does nothing
|
117
|
+
unless the implemenation used uses a hash tree. */
|
118
|
+
void * dwarf_initialize_search_hash( void **treeptr,
|
119
|
+
unsigned long(*hashfunc)(const void *key),
|
120
|
+
unsigned long size_estimate);
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
#endif /* DWARF_TSEARCH */
|
@@ -0,0 +1,675 @@
|
|
1
|
+
/* Copyright (c) 2013-2014, David Anderson
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with
|
5
|
+
or without modification, are permitted provided that the
|
6
|
+
following conditions are met:
|
7
|
+
|
8
|
+
Redistributions of source code must retain the above
|
9
|
+
copyright notice, this list of conditions and the following
|
10
|
+
disclaimer.
|
11
|
+
|
12
|
+
Redistributions in binary form must reproduce the above
|
13
|
+
copyright notice, this list of conditions and the following
|
14
|
+
disclaimer in the documentation and/or other materials
|
15
|
+
provided with the distribution.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
18
|
+
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
19
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
20
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
21
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
22
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
24
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
25
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
26
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
28
|
+
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
29
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
*/
|
32
|
+
|
33
|
+
|
34
|
+
/* The interfaces follow tsearch (See the Single
|
35
|
+
Unix Specification) but the implementation is
|
36
|
+
written without reference to the source of any
|
37
|
+
version of tsearch or any hashing code.
|
38
|
+
|
39
|
+
An additional interface is added (compared to
|
40
|
+
a real tsearch) to let the caller identify a
|
41
|
+
'hash' function with each hash table (called
|
42
|
+
a tree below, but that is a misnomer).
|
43
|
+
|
44
|
+
So read 'tree' below as hash table.
|
45
|
+
|
46
|
+
See http://www.prevanders.net/tsearch.html
|
47
|
+
for information and an example of use.
|
48
|
+
|
49
|
+
Based on Knuth, chapter 6.4
|
50
|
+
|
51
|
+
This uses a hash based on the key.
|
52
|
+
Collision resolution is by chaining.
|
53
|
+
|
54
|
+
twalk() and tdestroy() walk in a random order.
|
55
|
+
The 'preorder' etc labels mean nothing in a hash, so everything
|
56
|
+
is called a leaf.
|
57
|
+
|
58
|
+
*/
|
59
|
+
|
60
|
+
|
61
|
+
#include "config.h"
|
62
|
+
#include "dwarf_incl.h"
|
63
|
+
#include "stdlib.h" /* for free() etc */
|
64
|
+
#include <stdio.h> /* for printf() */
|
65
|
+
#include "dwarf_tsearch.h"
|
66
|
+
|
67
|
+
/* A table of primes used to size and resize the hash table.
|
68
|
+
From public sources of prime numbers, arbitrarily chosen
|
69
|
+
to approximately double in size at each step.
|
70
|
+
*/
|
71
|
+
static unsigned long long primes[] =
|
72
|
+
{
|
73
|
+
#if 1 /* for testing only */
|
74
|
+
5,11, 17,23, 31, 47, 53, 79,
|
75
|
+
#endif
|
76
|
+
1009,
|
77
|
+
5591,
|
78
|
+
10007,
|
79
|
+
21839,
|
80
|
+
41413,
|
81
|
+
99907,
|
82
|
+
199967,
|
83
|
+
400009,
|
84
|
+
800029,
|
85
|
+
1600141,
|
86
|
+
3000089,
|
87
|
+
6000121,
|
88
|
+
12000257,
|
89
|
+
24000143,
|
90
|
+
48000203,
|
91
|
+
100000127,
|
92
|
+
200001611,
|
93
|
+
400000669,
|
94
|
+
800000573,
|
95
|
+
0 /* Here we are giving up */
|
96
|
+
};
|
97
|
+
|
98
|
+
static unsigned long allowed_fill_percent = 90;
|
99
|
+
|
100
|
+
|
101
|
+
struct hs_base {
|
102
|
+
unsigned long tablesize_;
|
103
|
+
unsigned long tablesize_entry_index_;
|
104
|
+
unsigned long allowed_fill_;
|
105
|
+
/* Record_count means number of active records,
|
106
|
+
counting all records on chains.
|
107
|
+
When the record_count is > 90% of a full
|
108
|
+
tablesize_ we redo the table before adding
|
109
|
+
a new entry. */
|
110
|
+
unsigned long record_count_;
|
111
|
+
/* hashtab_ is an array of hs_entry,
|
112
|
+
indexes 0 through tablesize_ -1. */
|
113
|
+
struct ts_entry * hashtab_;
|
114
|
+
unsigned long (*hashfunc_)(const void *key);
|
115
|
+
};
|
116
|
+
|
117
|
+
struct ts_entry {
|
118
|
+
const void * keyptr;
|
119
|
+
/* So that a keyptr of 0 (if added) is
|
120
|
+
not confused with an empty hash slot,
|
121
|
+
we must mark used slots as used in the hash tab */
|
122
|
+
unsigned char entryused;
|
123
|
+
struct ts_entry *next;
|
124
|
+
};
|
125
|
+
|
126
|
+
enum search_intent_t
|
127
|
+
{
|
128
|
+
want_insert,
|
129
|
+
only_find,
|
130
|
+
want_delete
|
131
|
+
};
|
132
|
+
|
133
|
+
static struct ts_entry *
|
134
|
+
tsearch_inner( const void *key, struct hs_base* head,
|
135
|
+
int (*compar)(const void *, const void *),
|
136
|
+
const enum search_intent_t intent, int*inserted,
|
137
|
+
struct ts_entry **parent_ptr);
|
138
|
+
static void
|
139
|
+
dwarf_tdestroy_inner(struct hs_base*h,
|
140
|
+
void (*free_node)(void *nodep),
|
141
|
+
int depth);
|
142
|
+
|
143
|
+
|
144
|
+
/* A trivial integer-based percentage calculation.
|
145
|
+
Percents >100 are reasonable for a hash-with-chains
|
146
|
+
situation (even if they might not be the best choice
|
147
|
+
for performance). */
|
148
|
+
static unsigned long
|
149
|
+
calculate_allowed_fill(unsigned long fill_percent, unsigned long ct)
|
150
|
+
{
|
151
|
+
unsigned long v = 0;
|
152
|
+
if(ct < 100000) {
|
153
|
+
unsigned long v2 = (ct *fill_percent)/100;
|
154
|
+
return v2;
|
155
|
+
}
|
156
|
+
v = (ct /100)*fill_percent;
|
157
|
+
return v;
|
158
|
+
}
|
159
|
+
|
160
|
+
/* Initialize the hash and pass in the hash function.
|
161
|
+
If the entry count needed is unknown, pass in 0 as a count estimate,
|
162
|
+
but if the number of hash entries needed can be estimated,
|
163
|
+
pass in the estimate (which need not be prime, we actually use
|
164
|
+
the nearest higher prime from the above table).
|
165
|
+
If the estimated count is
|
166
|
+
Return the tree base, or return NULL if insufficient memory. */
|
167
|
+
void *
|
168
|
+
dwarf_initialize_search_hash( void **treeptr,
|
169
|
+
unsigned long(*hashfunc)(const void *key),
|
170
|
+
unsigned long size_estimate)
|
171
|
+
{
|
172
|
+
unsigned long prime_to_use =primes[0];
|
173
|
+
unsigned entry_index = 0;
|
174
|
+
unsigned k = 0;
|
175
|
+
struct hs_base *base = 0;
|
176
|
+
|
177
|
+
base = *(struct hs_base **)treeptr;
|
178
|
+
if(base) {
|
179
|
+
/* initalized already. */
|
180
|
+
return base ;
|
181
|
+
}
|
182
|
+
base = calloc(sizeof(struct hs_base),1);
|
183
|
+
if(!base) {
|
184
|
+
/* Out of memory. */
|
185
|
+
return NULL ;
|
186
|
+
}
|
187
|
+
prime_to_use = primes[0];
|
188
|
+
while(size_estimate && (size_estimate > prime_to_use)) {
|
189
|
+
k = k +1;
|
190
|
+
prime_to_use = primes[k];
|
191
|
+
if(prime_to_use == 0) {
|
192
|
+
/* Oops. Too large. */
|
193
|
+
free(base);
|
194
|
+
return NULL;
|
195
|
+
}
|
196
|
+
entry_index = k;
|
197
|
+
}
|
198
|
+
base->tablesize_ = prime_to_use;
|
199
|
+
base->allowed_fill_ = calculate_allowed_fill(allowed_fill_percent,
|
200
|
+
prime_to_use);
|
201
|
+
if( base->allowed_fill_< (base->tablesize_/2)) {
|
202
|
+
/* Oops. We are in trouble. Coding mistake here. */
|
203
|
+
return NULL;
|
204
|
+
}
|
205
|
+
base->record_count_ = 0;
|
206
|
+
base->tablesize_entry_index_ = entry_index;
|
207
|
+
/* hashtab_ is an array of hs_entry,
|
208
|
+
indexes 0 through tablesize_ -1. */
|
209
|
+
base->hashfunc_ = hashfunc;
|
210
|
+
base->hashtab_ = calloc(sizeof(struct ts_entry),base->tablesize_);
|
211
|
+
if(!base->hashtab_) {
|
212
|
+
free(base);
|
213
|
+
return NULL;
|
214
|
+
}
|
215
|
+
*treeptr = base;
|
216
|
+
return base;
|
217
|
+
}
|
218
|
+
|
219
|
+
|
220
|
+
static void print_entry(struct ts_entry *t,const char *descr,
|
221
|
+
char *(* keyprint)(const void *),
|
222
|
+
unsigned long hashpos,
|
223
|
+
unsigned long chainpos)
|
224
|
+
{
|
225
|
+
char *v = 0;
|
226
|
+
if(!t->entryused) {
|
227
|
+
return;
|
228
|
+
}
|
229
|
+
v = keyprint(t->keyptr);
|
230
|
+
printf(
|
231
|
+
"[%4lu.%02lu] 0x%08x <keyptr 0x%08x> <key %s> %s\n",
|
232
|
+
hashpos,chainpos,
|
233
|
+
(unsigned)t,
|
234
|
+
(unsigned)t->keyptr,
|
235
|
+
v,
|
236
|
+
descr);
|
237
|
+
}
|
238
|
+
|
239
|
+
/* For debugging */
|
240
|
+
static void
|
241
|
+
dumptree_inner(const struct hs_base *h,
|
242
|
+
char *(* keyprint)(const void *),
|
243
|
+
const char *descr, int printdetails)
|
244
|
+
{
|
245
|
+
unsigned long ix = 0;
|
246
|
+
unsigned long tsize = h->tablesize_;
|
247
|
+
struct ts_entry *p = &h->hashtab_[0];
|
248
|
+
unsigned long hashused = 0;
|
249
|
+
unsigned long maxchainlength = 0;
|
250
|
+
unsigned long chainsgt1 = 0;
|
251
|
+
printf("dumptree head ptr : 0x%08x size %lu entries %lu allowed %lu %s\n",
|
252
|
+
(unsigned)h,
|
253
|
+
h->tablesize_,
|
254
|
+
h->record_count_,
|
255
|
+
h->allowed_fill_,
|
256
|
+
descr);
|
257
|
+
for( ; ix < tsize; ix++,p++) {
|
258
|
+
unsigned long chainlength = 0;
|
259
|
+
struct ts_entry*n = 0;
|
260
|
+
int chainpos = 0;
|
261
|
+
if(p->entryused) {
|
262
|
+
++hashused;
|
263
|
+
chainlength = 1;
|
264
|
+
if(printdetails) {
|
265
|
+
print_entry(p,"head",keyprint,ix,chainpos);
|
266
|
+
}
|
267
|
+
}
|
268
|
+
chainpos++;
|
269
|
+
for(n = p->next; n ; n = n->next) {
|
270
|
+
chainlength++;
|
271
|
+
if(printdetails) {
|
272
|
+
print_entry(n,"chain",keyprint,ix,chainpos);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
if(chainlength > maxchainlength) {
|
276
|
+
maxchainlength = chainlength;
|
277
|
+
}
|
278
|
+
if (chainlength > 1) {
|
279
|
+
chainsgt1++;
|
280
|
+
}
|
281
|
+
}
|
282
|
+
printf("Hashtable: %lu of %lu hash entries used.\n",hashused,tsize);
|
283
|
+
printf("Hashtable: %lu chains length longer than 1. \n",chainsgt1);
|
284
|
+
printf("Hashtable: %lu is maximum chain length.\n",maxchainlength);
|
285
|
+
}
|
286
|
+
|
287
|
+
/* Dumping the tree.
|
288
|
+
*/
|
289
|
+
void
|
290
|
+
dwarf_tdump(const void*headp_in,
|
291
|
+
char *(* keyprint)(const void *),
|
292
|
+
const char *msg)
|
293
|
+
{
|
294
|
+
const struct hs_base *head = (const struct hs_base *)headp_in;
|
295
|
+
if(!head) {
|
296
|
+
printf("dumptree null tree ptr : %s\n",msg);
|
297
|
+
return;
|
298
|
+
}
|
299
|
+
dumptree_inner(head,keyprint,msg,1);
|
300
|
+
}
|
301
|
+
|
302
|
+
static struct ts_entry *
|
303
|
+
allocate_ts_entry(const void *key)
|
304
|
+
{
|
305
|
+
struct ts_entry *e = (struct ts_entry *)
|
306
|
+
malloc(sizeof(struct ts_entry));
|
307
|
+
if(!e) {
|
308
|
+
return NULL;
|
309
|
+
}
|
310
|
+
e->keyptr = key;
|
311
|
+
e->entryused = 1;
|
312
|
+
e->next = 0;
|
313
|
+
return e;
|
314
|
+
}
|
315
|
+
|
316
|
+
static void
|
317
|
+
resize_table(struct hs_base *head,
|
318
|
+
int (*compar)(const void *, const void *))
|
319
|
+
{
|
320
|
+
struct hs_base newhead;
|
321
|
+
unsigned new_entry_index = 0;
|
322
|
+
unsigned long prime_to_use = 0;
|
323
|
+
|
324
|
+
/* Copy the values we have. */
|
325
|
+
newhead = *head;
|
326
|
+
/* But drop the hashtab_ from new. calloc below. */
|
327
|
+
newhead.hashtab_ = 0;
|
328
|
+
newhead.record_count_ = 0;
|
329
|
+
new_entry_index = head->tablesize_entry_index_ +1;
|
330
|
+
prime_to_use = primes[new_entry_index];
|
331
|
+
if(prime_to_use == 0) {
|
332
|
+
/* Oops, too large. Leave table size as is, though
|
333
|
+
it will get slow as it overfills. */
|
334
|
+
return;
|
335
|
+
}
|
336
|
+
newhead.tablesize_ = prime_to_use;
|
337
|
+
newhead.allowed_fill_ = calculate_allowed_fill(allowed_fill_percent,
|
338
|
+
prime_to_use);
|
339
|
+
if( newhead.allowed_fill_< (newhead.tablesize_/2)) {
|
340
|
+
/* Oops. We are in trouble. */
|
341
|
+
return;
|
342
|
+
}
|
343
|
+
newhead.tablesize_entry_index_ = new_entry_index;
|
344
|
+
newhead.hashtab_ = calloc(sizeof(struct ts_entry),newhead.tablesize_);
|
345
|
+
if(!newhead.hashtab_) {
|
346
|
+
/* Oops, too large. Leave table size as is, though
|
347
|
+
things will get slow as it overfills. */
|
348
|
+
free(newhead.hashtab_);
|
349
|
+
return;
|
350
|
+
}
|
351
|
+
{
|
352
|
+
/* Insert all the records from the old table into
|
353
|
+
the new table. */
|
354
|
+
int fillnewfail = 0;
|
355
|
+
unsigned long ix = 0;
|
356
|
+
unsigned long tsize = head->tablesize_;
|
357
|
+
struct ts_entry *p = &head->hashtab_[0];
|
358
|
+
for( ; ix < tsize; ix++,p++) {
|
359
|
+
int inserted = 0;
|
360
|
+
struct ts_entry*n = 0;
|
361
|
+
if(fillnewfail) {
|
362
|
+
break;
|
363
|
+
}
|
364
|
+
if(p->keyptr) {
|
365
|
+
tsearch_inner(p->keyptr,
|
366
|
+
&newhead,compar,
|
367
|
+
want_insert,
|
368
|
+
&inserted,
|
369
|
+
0);
|
370
|
+
if(!inserted) {
|
371
|
+
fillnewfail = 1;
|
372
|
+
break;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
for(n = p->next; n ; n = n->next) {
|
376
|
+
inserted = 0;
|
377
|
+
tsearch_inner(n->keyptr,
|
378
|
+
&newhead,compar,
|
379
|
+
want_insert,
|
380
|
+
&inserted,
|
381
|
+
0);
|
382
|
+
if(!inserted) {
|
383
|
+
fillnewfail = 1;
|
384
|
+
break;
|
385
|
+
}
|
386
|
+
}
|
387
|
+
}
|
388
|
+
if(fillnewfail) {
|
389
|
+
free(newhead.hashtab_);
|
390
|
+
return;
|
391
|
+
}
|
392
|
+
}
|
393
|
+
/* Now get rid of the chain entries of the old table. */
|
394
|
+
dwarf_tdestroy_inner(head,0,0);
|
395
|
+
/* Now get rid of the old table itself. */
|
396
|
+
free(head->hashtab_);
|
397
|
+
head->hashtab_ = 0;
|
398
|
+
*head = newhead;
|
399
|
+
return;
|
400
|
+
}
|
401
|
+
|
402
|
+
/* Inner search of the hash and synonym chains.
|
403
|
+
*/
|
404
|
+
static struct ts_entry *
|
405
|
+
tsearch_inner( const void *key, struct hs_base* head,
|
406
|
+
int (*compar)(const void *, const void *),
|
407
|
+
const enum search_intent_t intent, int*inserted,
|
408
|
+
/* owner_ptr used for delete. Only set
|
409
|
+
if the to-be-deleted item is on a chain,
|
410
|
+
not in the hashtab. Points to the item
|
411
|
+
pointing to the to-be-deleted-item.*/
|
412
|
+
struct ts_entry **owner_ptr)
|
413
|
+
{
|
414
|
+
struct ts_entry *s =0;
|
415
|
+
struct ts_entry *c =0;
|
416
|
+
struct ts_entry *q =0;
|
417
|
+
int kc = 0;
|
418
|
+
unsigned long keyhash = 0;
|
419
|
+
unsigned long hindx = 0;
|
420
|
+
struct ts_entry *chain_parent = 0;
|
421
|
+
|
422
|
+
if(! head->hashfunc_) {
|
423
|
+
/* Not fully initialized. */
|
424
|
+
return NULL;
|
425
|
+
}
|
426
|
+
keyhash = head->hashfunc_(key);
|
427
|
+
if (intent == want_insert) {
|
428
|
+
if( head->record_count_ > head->allowed_fill_) {
|
429
|
+
resize_table(head,compar);
|
430
|
+
}
|
431
|
+
}
|
432
|
+
hindx = keyhash%head->tablesize_;
|
433
|
+
s = &head->hashtab_[hindx];
|
434
|
+
if(!s->entryused) {
|
435
|
+
/* Not found. */
|
436
|
+
if(intent != want_insert) {
|
437
|
+
return NULL;
|
438
|
+
}
|
439
|
+
/* Insert in the base hash table in an
|
440
|
+
empty slot. */
|
441
|
+
*inserted = 1;
|
442
|
+
head->record_count_++;
|
443
|
+
s->keyptr = (const void *)key;
|
444
|
+
s->entryused = 1;
|
445
|
+
s->next = 0;
|
446
|
+
return s;
|
447
|
+
}
|
448
|
+
kc = compar(key,s->keyptr);
|
449
|
+
if(kc == 0 ) {
|
450
|
+
/* found! */
|
451
|
+
if(want_delete) {
|
452
|
+
*owner_ptr = 0;
|
453
|
+
}
|
454
|
+
return (void *)&(s->keyptr);
|
455
|
+
}
|
456
|
+
chain_parent = s;
|
457
|
+
for(c = s->next; c; c = c->next) {
|
458
|
+
kc = compar(key,c->keyptr);
|
459
|
+
if(kc == 0 ) {
|
460
|
+
/* found! */
|
461
|
+
if(want_delete) {
|
462
|
+
*owner_ptr = chain_parent;
|
463
|
+
}
|
464
|
+
return (void *)&(c->keyptr);
|
465
|
+
}
|
466
|
+
chain_parent = c;
|
467
|
+
}
|
468
|
+
if(intent != want_insert) {
|
469
|
+
return NULL;
|
470
|
+
}
|
471
|
+
/* Insert following head record of the chain. */
|
472
|
+
q = allocate_ts_entry(key);
|
473
|
+
if (!q) {
|
474
|
+
return q;
|
475
|
+
}
|
476
|
+
q->next = s->next;
|
477
|
+
s->next = q;
|
478
|
+
head->record_count_++;
|
479
|
+
*inserted = 1;
|
480
|
+
return q;
|
481
|
+
}
|
482
|
+
/* Search and, if missing, insert. */
|
483
|
+
void *
|
484
|
+
dwarf_tsearch(const void *key, void **headin,
|
485
|
+
int (*compar)(const void *, const void *))
|
486
|
+
{
|
487
|
+
struct hs_base **rootp = (struct hs_base **)headin;
|
488
|
+
struct hs_base *head = *rootp;
|
489
|
+
struct ts_entry *r = 0;
|
490
|
+
int inserted = 0;
|
491
|
+
/* nullme won't be set. */
|
492
|
+
struct ts_entry *nullme = 0;
|
493
|
+
|
494
|
+
if (!head) {
|
495
|
+
/* something is wrong here, not initialized. */
|
496
|
+
return NULL;
|
497
|
+
}
|
498
|
+
r = tsearch_inner(key,head,compar,want_insert,&inserted,&nullme);
|
499
|
+
if (!r) {
|
500
|
+
return NULL;
|
501
|
+
}
|
502
|
+
return (void *)&(r->keyptr);
|
503
|
+
}
|
504
|
+
|
505
|
+
|
506
|
+
/* Search. */
|
507
|
+
void *
|
508
|
+
dwarf_tfind(const void *key, void *const *rootp,
|
509
|
+
int (*compar)(const void *, const void *))
|
510
|
+
{
|
511
|
+
/* Nothing will change, but we discard const
|
512
|
+
so we can use tsearch_inner(). */
|
513
|
+
struct hs_base **proot = (struct hs_base **)rootp;
|
514
|
+
struct hs_base *head = *proot;
|
515
|
+
struct ts_entry *r = 0;
|
516
|
+
/* inserted flag won't be set. */
|
517
|
+
int inserted = 0;
|
518
|
+
/* nullme won't be set. */
|
519
|
+
struct ts_entry * nullme = 0;
|
520
|
+
/* Get to actual tree. */
|
521
|
+
|
522
|
+
if (!head) {
|
523
|
+
return NULL;
|
524
|
+
}
|
525
|
+
|
526
|
+
r = tsearch_inner(key,head,compar,only_find,&inserted,&nullme);
|
527
|
+
if(!r) {
|
528
|
+
return NULL;
|
529
|
+
}
|
530
|
+
return (void *)(&(r->keyptr));
|
531
|
+
}
|
532
|
+
|
533
|
+
/* Unlike the simple binary tree case,
|
534
|
+
a fully-empty hash situation does not null the *rootp
|
535
|
+
*/
|
536
|
+
void *
|
537
|
+
dwarf_tdelete(const void *key, void **rootp,
|
538
|
+
int (*compar)(const void *, const void *))
|
539
|
+
{
|
540
|
+
struct hs_base **proot = (struct hs_base **)rootp;
|
541
|
+
struct hs_base *head = *proot;
|
542
|
+
struct ts_entry *found = 0;
|
543
|
+
/* inserted flag won't be set. */
|
544
|
+
int inserted = 0;
|
545
|
+
struct ts_entry * parentp = 0;
|
546
|
+
|
547
|
+
if (!head) {
|
548
|
+
return NULL;
|
549
|
+
}
|
550
|
+
|
551
|
+
found = tsearch_inner(key,head,compar,want_delete,&inserted,
|
552
|
+
&parentp);
|
553
|
+
if(found) {
|
554
|
+
if(parentp) {
|
555
|
+
/* Delete a chain entry. */
|
556
|
+
head->record_count_--;
|
557
|
+
parentp->next = found->next;
|
558
|
+
/* We free our storage. It would be up
|
559
|
+
to caller to do a tfind to find
|
560
|
+
a record and delete content if necessary. */
|
561
|
+
free(found);
|
562
|
+
return (void *)&(parentp->keyptr);
|
563
|
+
}
|
564
|
+
/* So found is the head of a chain. */
|
565
|
+
if(found->next) {
|
566
|
+
/* Delete a chain entry, pull up to hash tab, freeing
|
567
|
+
up the chain entry. */
|
568
|
+
struct ts_entry *pullup = found->next;
|
569
|
+
*found = *pullup;
|
570
|
+
free(pullup);
|
571
|
+
head->record_count_--;
|
572
|
+
return (void *)&(found->keyptr);
|
573
|
+
} else {
|
574
|
+
/* Delete a main hash table entry.
|
575
|
+
Problem: what the heck to return as a keyptr pointer?
|
576
|
+
Well, we return NULL. As in the standard
|
577
|
+
tsearch, returning NULL does not mean
|
578
|
+
failure! Here it just means 'empty chain somewhere'.
|
579
|
+
*/
|
580
|
+
head->record_count_--;
|
581
|
+
found->next = 0;
|
582
|
+
found->keyptr = 0;
|
583
|
+
found->entryused = 0;
|
584
|
+
return NULL;
|
585
|
+
}
|
586
|
+
}
|
587
|
+
return NULL;
|
588
|
+
}
|
589
|
+
|
590
|
+
static void
|
591
|
+
dwarf_twalk_inner(const struct hs_base *h,
|
592
|
+
struct ts_entry *p,
|
593
|
+
void (*action)(const void *nodep, const DW_VISIT which, const int depth),
|
594
|
+
unsigned level)
|
595
|
+
{
|
596
|
+
unsigned long ix = 0;
|
597
|
+
unsigned long tsize = h->tablesize_;
|
598
|
+
for( ; ix < tsize; ix++,p++) {
|
599
|
+
struct ts_entry*n = 0;
|
600
|
+
if(p->keyptr) {
|
601
|
+
action((void *)(&(p->keyptr)),dwarf_leaf,level);
|
602
|
+
}
|
603
|
+
for(n = p->next; n ; n = n->next) {
|
604
|
+
action((void *)(&(n->keyptr)),dwarf_leaf,level);
|
605
|
+
}
|
606
|
+
}
|
607
|
+
}
|
608
|
+
|
609
|
+
void
|
610
|
+
dwarf_twalk(const void *rootp,
|
611
|
+
void (*action)(const void *nodep, const DW_VISIT which, const int depth))
|
612
|
+
{
|
613
|
+
const struct hs_base *head = (const struct hs_base *)rootp;
|
614
|
+
struct ts_entry *root = 0;
|
615
|
+
if(!head) {
|
616
|
+
return;
|
617
|
+
}
|
618
|
+
root = head->hashtab_;
|
619
|
+
/* Get to actual tree. */
|
620
|
+
dwarf_twalk_inner(head,root,action,0);
|
621
|
+
}
|
622
|
+
|
623
|
+
static void
|
624
|
+
dwarf_tdestroy_inner(struct hs_base*h,
|
625
|
+
void (*free_node)(void *nodep),
|
626
|
+
int depth)
|
627
|
+
{
|
628
|
+
unsigned long ix = 0;
|
629
|
+
unsigned long tsize = h->tablesize_;
|
630
|
+
struct ts_entry *p = &h->hashtab_[0];
|
631
|
+
for( ; ix < tsize; ix++,p++) {
|
632
|
+
struct ts_entry*n = 0;
|
633
|
+
struct ts_entry*prev = 0;
|
634
|
+
if(p->keyptr && p->entryused) {
|
635
|
+
if(free_node) {
|
636
|
+
free_node((void *)(p->keyptr));
|
637
|
+
}
|
638
|
+
--h->record_count_;
|
639
|
+
}
|
640
|
+
/* Now walk and free up the chain entries. */
|
641
|
+
for(n = p->next; n ; ) {
|
642
|
+
if(free_node) {
|
643
|
+
free_node((void *)(n->keyptr));
|
644
|
+
}
|
645
|
+
--h->record_count_;
|
646
|
+
prev = n;
|
647
|
+
n = n->next;
|
648
|
+
free(prev);
|
649
|
+
}
|
650
|
+
}
|
651
|
+
}
|
652
|
+
|
653
|
+
/* Walk the tree, freeing all space in the tree
|
654
|
+
and calling the user's callback function on each node.
|
655
|
+
|
656
|
+
It is up to the caller to zero out anything pointing to
|
657
|
+
head (ie, that has the value rootp holds) after this
|
658
|
+
returns.
|
659
|
+
*/
|
660
|
+
void
|
661
|
+
dwarf_tdestroy(void *rootp, void (*free_node)(void *nodep))
|
662
|
+
{
|
663
|
+
struct hs_base *head = (struct hs_base *)rootp;
|
664
|
+
struct ts_entry *root = 0;
|
665
|
+
if(!head) {
|
666
|
+
return;
|
667
|
+
}
|
668
|
+
root = head->hashtab_;
|
669
|
+
dwarf_tdestroy_inner(head,free_node,0);
|
670
|
+
free(root);
|
671
|
+
free(head);
|
672
|
+
}
|
673
|
+
|
674
|
+
|
675
|
+
|