rdwarf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +28 -0
  6. data/README.md +39 -0
  7. data/Rakefile +8 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +7 -0
  10. data/ext/rdwarf/depend +5 -0
  11. data/ext/rdwarf/extconf.rb +29 -0
  12. data/ext/rdwarf/libdwarf/CHANGES +102 -0
  13. data/ext/rdwarf/libdwarf/CODINGSTYLE +71 -0
  14. data/ext/rdwarf/libdwarf/COPYING +28 -0
  15. data/ext/rdwarf/libdwarf/ChangeLog +619 -0
  16. data/ext/rdwarf/libdwarf/ChangeLog2006 +835 -0
  17. data/ext/rdwarf/libdwarf/ChangeLog2007 +217 -0
  18. data/ext/rdwarf/libdwarf/ChangeLog2008 +263 -0
  19. data/ext/rdwarf/libdwarf/ChangeLog2009 +348 -0
  20. data/ext/rdwarf/libdwarf/ChangeLog2010 +175 -0
  21. data/ext/rdwarf/libdwarf/ChangeLog2011 +297 -0
  22. data/ext/rdwarf/libdwarf/ChangeLog2012 +131 -0
  23. data/ext/rdwarf/libdwarf/ChangeLog2013 +238 -0
  24. data/ext/rdwarf/libdwarf/ChangeLog2014 +399 -0
  25. data/ext/rdwarf/libdwarf/LGPL.txt +504 -0
  26. data/ext/rdwarf/libdwarf/LIBDWARFCOPYRIGHT +40 -0
  27. data/ext/rdwarf/libdwarf/Makefile.in +220 -0
  28. data/ext/rdwarf/libdwarf/NEWS +535 -0
  29. data/ext/rdwarf/libdwarf/README +235 -0
  30. data/ext/rdwarf/libdwarf/checkexamples.c +1179 -0
  31. data/ext/rdwarf/libdwarf/cmplrs/dwarf_addr_finder.h +55 -0
  32. data/ext/rdwarf/libdwarf/common.c +62 -0
  33. data/ext/rdwarf/libdwarf/common.h +38 -0
  34. data/ext/rdwarf/libdwarf/config.h.in +146 -0
  35. data/ext/rdwarf/libdwarf/configure +5581 -0
  36. data/ext/rdwarf/libdwarf/configure.in +167 -0
  37. data/ext/rdwarf/libdwarf/dw-linetableheader.txt +39 -0
  38. data/ext/rdwarf/libdwarf/dwarf.h +1342 -0
  39. data/ext/rdwarf/libdwarf/dwarf_abbrev.c +291 -0
  40. data/ext/rdwarf/libdwarf/dwarf_abbrev.h +45 -0
  41. data/ext/rdwarf/libdwarf/dwarf_addr_finder.c +676 -0
  42. data/ext/rdwarf/libdwarf/dwarf_alloc.c +685 -0
  43. data/ext/rdwarf/libdwarf/dwarf_alloc.h +38 -0
  44. data/ext/rdwarf/libdwarf/dwarf_arange.c +595 -0
  45. data/ext/rdwarf/libdwarf/dwarf_arange.h +62 -0
  46. data/ext/rdwarf/libdwarf/dwarf_base_types.h +157 -0
  47. data/ext/rdwarf/libdwarf/dwarf_die_deliv.c +1802 -0
  48. data/ext/rdwarf/libdwarf/dwarf_die_deliv.h +46 -0
  49. data/ext/rdwarf/libdwarf/dwarf_elf_access.c +1348 -0
  50. data/ext/rdwarf/libdwarf/dwarf_elf_access.h +46 -0
  51. data/ext/rdwarf/libdwarf/dwarf_error.c +492 -0
  52. data/ext/rdwarf/libdwarf/dwarf_error.h +53 -0
  53. data/ext/rdwarf/libdwarf/dwarf_form.c +1302 -0
  54. data/ext/rdwarf/libdwarf/dwarf_frame.c +2454 -0
  55. data/ext/rdwarf/libdwarf/dwarf_frame.h +418 -0
  56. data/ext/rdwarf/libdwarf/dwarf_frame2.c +1533 -0
  57. data/ext/rdwarf/libdwarf/dwarf_frame3.c +282 -0
  58. data/ext/rdwarf/libdwarf/dwarf_funcs.c +123 -0
  59. data/ext/rdwarf/libdwarf/dwarf_funcs.h +33 -0
  60. data/ext/rdwarf/libdwarf/dwarf_gdbindex.c +520 -0
  61. data/ext/rdwarf/libdwarf/dwarf_gdbindex.h +97 -0
  62. data/ext/rdwarf/libdwarf/dwarf_global.c +612 -0
  63. data/ext/rdwarf/libdwarf/dwarf_global.h +117 -0
  64. data/ext/rdwarf/libdwarf/dwarf_harmless.c +228 -0
  65. data/ext/rdwarf/libdwarf/dwarf_harmless.h +31 -0
  66. data/ext/rdwarf/libdwarf/dwarf_incl.h +61 -0
  67. data/ext/rdwarf/libdwarf/dwarf_init_finish.c +1263 -0
  68. data/ext/rdwarf/libdwarf/dwarf_leb.c +159 -0
  69. data/ext/rdwarf/libdwarf/dwarf_line.c +1822 -0
  70. data/ext/rdwarf/libdwarf/dwarf_line.h +446 -0
  71. data/ext/rdwarf/libdwarf/dwarf_line2.c +98 -0
  72. data/ext/rdwarf/libdwarf/dwarf_line_table_reader_common.c +1583 -0
  73. data/ext/rdwarf/libdwarf/dwarf_loc.c +1525 -0
  74. data/ext/rdwarf/libdwarf/dwarf_loc.h +149 -0
  75. data/ext/rdwarf/libdwarf/dwarf_loc2.c +833 -0
  76. data/ext/rdwarf/libdwarf/dwarf_macro.c +479 -0
  77. data/ext/rdwarf/libdwarf/dwarf_macro.h +35 -0
  78. data/ext/rdwarf/libdwarf/dwarf_opaque.h +778 -0
  79. data/ext/rdwarf/libdwarf/dwarf_original_elf_init.c +219 -0
  80. data/ext/rdwarf/libdwarf/dwarf_print_lines.c +631 -0
  81. data/ext/rdwarf/libdwarf/dwarf_pubtypes.c +132 -0
  82. data/ext/rdwarf/libdwarf/dwarf_query.c +1594 -0
  83. data/ext/rdwarf/libdwarf/dwarf_ranges.c +194 -0
  84. data/ext/rdwarf/libdwarf/dwarf_reloc_arm.h +308 -0
  85. data/ext/rdwarf/libdwarf/dwarf_reloc_mips.h +117 -0
  86. data/ext/rdwarf/libdwarf/dwarf_reloc_ppc.h +242 -0
  87. data/ext/rdwarf/libdwarf/dwarf_reloc_ppc64.h +272 -0
  88. data/ext/rdwarf/libdwarf/dwarf_reloc_x86_64.h +127 -0
  89. data/ext/rdwarf/libdwarf/dwarf_sort_line.c +665 -0
  90. data/ext/rdwarf/libdwarf/dwarf_string.c +82 -0
  91. data/ext/rdwarf/libdwarf/dwarf_stubs.c +38 -0
  92. data/ext/rdwarf/libdwarf/dwarf_tied.c +423 -0
  93. data/ext/rdwarf/libdwarf/dwarf_tsearch.h +125 -0
  94. data/ext/rdwarf/libdwarf/dwarf_tsearchhash.c +675 -0
  95. data/ext/rdwarf/libdwarf/dwarf_types.c +121 -0
  96. data/ext/rdwarf/libdwarf/dwarf_types.h +32 -0
  97. data/ext/rdwarf/libdwarf/dwarf_util.c +913 -0
  98. data/ext/rdwarf/libdwarf/dwarf_util.h +324 -0
  99. data/ext/rdwarf/libdwarf/dwarf_vars.c +125 -0
  100. data/ext/rdwarf/libdwarf/dwarf_vars.h +29 -0
  101. data/ext/rdwarf/libdwarf/dwarf_weaks.c +123 -0
  102. data/ext/rdwarf/libdwarf/dwarf_weaks.h +29 -0
  103. data/ext/rdwarf/libdwarf/dwarf_xu_index.c +579 -0
  104. data/ext/rdwarf/libdwarf/dwarf_xu_index.h +68 -0
  105. data/ext/rdwarf/libdwarf/dwgetopt.c +181 -0
  106. data/ext/rdwarf/libdwarf/dwgetopt.h +51 -0
  107. data/ext/rdwarf/libdwarf/gennames.c +531 -0
  108. data/ext/rdwarf/libdwarf/install.sh +119 -0
  109. data/ext/rdwarf/libdwarf/libdwarf.h.in +3746 -0
  110. data/ext/rdwarf/libdwarf/libdwarf2.1.mm +9805 -0
  111. data/ext/rdwarf/libdwarf/libdwarf2.1.pdf +0 -0
  112. data/ext/rdwarf/libdwarf/libdwarf2p.1.mm +2807 -0
  113. data/ext/rdwarf/libdwarf/libdwarf2p.1.pdf +0 -0
  114. data/ext/rdwarf/libdwarf/libdwarfdefs.h +81 -0
  115. data/ext/rdwarf/libdwarf/malloc_check.c +327 -0
  116. data/ext/rdwarf/libdwarf/malloc_check.h +52 -0
  117. data/ext/rdwarf/libdwarf/mips_extensions.mm +1266 -0
  118. data/ext/rdwarf/libdwarf/mips_extensions.pdf +0 -0
  119. data/ext/rdwarf/libdwarf/pro_alloc.c +179 -0
  120. data/ext/rdwarf/libdwarf/pro_alloc.h +33 -0
  121. data/ext/rdwarf/libdwarf/pro_arange.c +310 -0
  122. data/ext/rdwarf/libdwarf/pro_arange.h +51 -0
  123. data/ext/rdwarf/libdwarf/pro_die.c +431 -0
  124. data/ext/rdwarf/libdwarf/pro_die.h +59 -0
  125. data/ext/rdwarf/libdwarf/pro_encode_nm.c +108 -0
  126. data/ext/rdwarf/libdwarf/pro_encode_nm.h +39 -0
  127. data/ext/rdwarf/libdwarf/pro_error.c +96 -0
  128. data/ext/rdwarf/libdwarf/pro_error.h +43 -0
  129. data/ext/rdwarf/libdwarf/pro_expr.c +575 -0
  130. data/ext/rdwarf/libdwarf/pro_expr.h +36 -0
  131. data/ext/rdwarf/libdwarf/pro_finish.c +45 -0
  132. data/ext/rdwarf/libdwarf/pro_forms.c +1271 -0
  133. data/ext/rdwarf/libdwarf/pro_frame.c +572 -0
  134. data/ext/rdwarf/libdwarf/pro_frame.h +120 -0
  135. data/ext/rdwarf/libdwarf/pro_funcs.c +50 -0
  136. data/ext/rdwarf/libdwarf/pro_incl.h +91 -0
  137. data/ext/rdwarf/libdwarf/pro_init.c +327 -0
  138. data/ext/rdwarf/libdwarf/pro_line.c +373 -0
  139. data/ext/rdwarf/libdwarf/pro_line.h +112 -0
  140. data/ext/rdwarf/libdwarf/pro_macinfo.c +457 -0
  141. data/ext/rdwarf/libdwarf/pro_macinfo.h +31 -0
  142. data/ext/rdwarf/libdwarf/pro_opaque.h +513 -0
  143. data/ext/rdwarf/libdwarf/pro_pubnames.c +60 -0
  144. data/ext/rdwarf/libdwarf/pro_reloc.c +253 -0
  145. data/ext/rdwarf/libdwarf/pro_reloc.h +38 -0
  146. data/ext/rdwarf/libdwarf/pro_reloc_stream.c +256 -0
  147. data/ext/rdwarf/libdwarf/pro_reloc_stream.h +52 -0
  148. data/ext/rdwarf/libdwarf/pro_reloc_symbolic.c +245 -0
  149. data/ext/rdwarf/libdwarf/pro_reloc_symbolic.h +45 -0
  150. data/ext/rdwarf/libdwarf/pro_section.c +2233 -0
  151. data/ext/rdwarf/libdwarf/pro_section.h +100 -0
  152. data/ext/rdwarf/libdwarf/pro_types.c +274 -0
  153. data/ext/rdwarf/libdwarf/pro_types.h +34 -0
  154. data/ext/rdwarf/libdwarf/pro_util.h +38 -0
  155. data/ext/rdwarf/libdwarf/pro_vars.c +52 -0
  156. data/ext/rdwarf/libdwarf/pro_weaks.c +51 -0
  157. data/ext/rdwarf/rdwarf.c +765 -0
  158. data/ext/rdwarf/rdwarf.h +52 -0
  159. data/ext/rdwarf/rdwarf_names_gen.rb +109 -0
  160. data/lib/rdwarf.rb +181 -0
  161. data/lib/rdwarf/version.rb +3 -0
  162. data/rdwarf.gemspec +30 -0
  163. 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
+