jk-ferret 0.11.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (228) hide show
  1. data/CHANGELOG +24 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +90 -0
  4. data/RELEASE_CHANGES +137 -0
  5. data/RELEASE_NOTES +60 -0
  6. data/Rakefile +443 -0
  7. data/TODO +109 -0
  8. data/TUTORIAL +231 -0
  9. data/bin/ferret-browser +79 -0
  10. data/ext/BZLIB_blocksort.c +1094 -0
  11. data/ext/BZLIB_bzlib.c +1578 -0
  12. data/ext/BZLIB_compress.c +672 -0
  13. data/ext/BZLIB_crctable.c +104 -0
  14. data/ext/BZLIB_decompress.c +626 -0
  15. data/ext/BZLIB_huffman.c +205 -0
  16. data/ext/BZLIB_randtable.c +84 -0
  17. data/ext/STEMMER_api.c +66 -0
  18. data/ext/STEMMER_libstemmer.c +93 -0
  19. data/ext/STEMMER_stem_ISO_8859_1_danish.c +337 -0
  20. data/ext/STEMMER_stem_ISO_8859_1_dutch.c +624 -0
  21. data/ext/STEMMER_stem_ISO_8859_1_english.c +1117 -0
  22. data/ext/STEMMER_stem_ISO_8859_1_finnish.c +762 -0
  23. data/ext/STEMMER_stem_ISO_8859_1_french.c +1246 -0
  24. data/ext/STEMMER_stem_ISO_8859_1_german.c +503 -0
  25. data/ext/STEMMER_stem_ISO_8859_1_hungarian.c +1230 -0
  26. data/ext/STEMMER_stem_ISO_8859_1_italian.c +1065 -0
  27. data/ext/STEMMER_stem_ISO_8859_1_norwegian.c +297 -0
  28. data/ext/STEMMER_stem_ISO_8859_1_porter.c +749 -0
  29. data/ext/STEMMER_stem_ISO_8859_1_portuguese.c +1017 -0
  30. data/ext/STEMMER_stem_ISO_8859_1_spanish.c +1093 -0
  31. data/ext/STEMMER_stem_ISO_8859_1_swedish.c +307 -0
  32. data/ext/STEMMER_stem_ISO_8859_2_romanian.c +998 -0
  33. data/ext/STEMMER_stem_KOI8_R_russian.c +700 -0
  34. data/ext/STEMMER_stem_UTF_8_danish.c +339 -0
  35. data/ext/STEMMER_stem_UTF_8_dutch.c +634 -0
  36. data/ext/STEMMER_stem_UTF_8_english.c +1125 -0
  37. data/ext/STEMMER_stem_UTF_8_finnish.c +768 -0
  38. data/ext/STEMMER_stem_UTF_8_french.c +1256 -0
  39. data/ext/STEMMER_stem_UTF_8_german.c +509 -0
  40. data/ext/STEMMER_stem_UTF_8_hungarian.c +1234 -0
  41. data/ext/STEMMER_stem_UTF_8_italian.c +1073 -0
  42. data/ext/STEMMER_stem_UTF_8_norwegian.c +299 -0
  43. data/ext/STEMMER_stem_UTF_8_porter.c +755 -0
  44. data/ext/STEMMER_stem_UTF_8_portuguese.c +1023 -0
  45. data/ext/STEMMER_stem_UTF_8_romanian.c +1004 -0
  46. data/ext/STEMMER_stem_UTF_8_russian.c +694 -0
  47. data/ext/STEMMER_stem_UTF_8_spanish.c +1097 -0
  48. data/ext/STEMMER_stem_UTF_8_swedish.c +309 -0
  49. data/ext/STEMMER_stem_UTF_8_turkish.c +2205 -0
  50. data/ext/STEMMER_utilities.c +478 -0
  51. data/ext/analysis.c +1710 -0
  52. data/ext/analysis.h +266 -0
  53. data/ext/api.h +26 -0
  54. data/ext/array.c +125 -0
  55. data/ext/array.h +62 -0
  56. data/ext/bitvector.c +96 -0
  57. data/ext/bitvector.h +594 -0
  58. data/ext/bzlib.h +282 -0
  59. data/ext/bzlib_private.h +503 -0
  60. data/ext/compound_io.c +384 -0
  61. data/ext/config.h +52 -0
  62. data/ext/document.c +159 -0
  63. data/ext/document.h +63 -0
  64. data/ext/except.c +102 -0
  65. data/ext/except.h +176 -0
  66. data/ext/extconf.rb +15 -0
  67. data/ext/ferret.c +416 -0
  68. data/ext/ferret.h +94 -0
  69. data/ext/field_index.c +262 -0
  70. data/ext/field_index.h +52 -0
  71. data/ext/filter.c +157 -0
  72. data/ext/fs_store.c +493 -0
  73. data/ext/global.c +458 -0
  74. data/ext/global.h +302 -0
  75. data/ext/hash.c +524 -0
  76. data/ext/hash.h +515 -0
  77. data/ext/hashset.c +192 -0
  78. data/ext/hashset.h +215 -0
  79. data/ext/header.h +58 -0
  80. data/ext/helper.c +63 -0
  81. data/ext/helper.h +21 -0
  82. data/ext/index.c +6804 -0
  83. data/ext/index.h +935 -0
  84. data/ext/internal.h +1019 -0
  85. data/ext/lang.c +10 -0
  86. data/ext/lang.h +68 -0
  87. data/ext/libstemmer.h +79 -0
  88. data/ext/mempool.c +88 -0
  89. data/ext/mempool.h +43 -0
  90. data/ext/modules.h +190 -0
  91. data/ext/multimapper.c +351 -0
  92. data/ext/multimapper.h +60 -0
  93. data/ext/posh.c +1006 -0
  94. data/ext/posh.h +973 -0
  95. data/ext/priorityqueue.c +149 -0
  96. data/ext/priorityqueue.h +155 -0
  97. data/ext/q_boolean.c +1621 -0
  98. data/ext/q_const_score.c +162 -0
  99. data/ext/q_filtered_query.c +212 -0
  100. data/ext/q_fuzzy.c +280 -0
  101. data/ext/q_match_all.c +149 -0
  102. data/ext/q_multi_term.c +673 -0
  103. data/ext/q_parser.c +3103 -0
  104. data/ext/q_phrase.c +1206 -0
  105. data/ext/q_prefix.c +98 -0
  106. data/ext/q_range.c +682 -0
  107. data/ext/q_span.c +2390 -0
  108. data/ext/q_term.c +337 -0
  109. data/ext/q_wildcard.c +167 -0
  110. data/ext/r_analysis.c +2626 -0
  111. data/ext/r_index.c +3468 -0
  112. data/ext/r_qparser.c +635 -0
  113. data/ext/r_search.c +4490 -0
  114. data/ext/r_store.c +513 -0
  115. data/ext/r_utils.c +1131 -0
  116. data/ext/ram_store.c +476 -0
  117. data/ext/scanner.c +895 -0
  118. data/ext/scanner.h +36 -0
  119. data/ext/scanner_mb.c +6701 -0
  120. data/ext/scanner_utf8.c +4415 -0
  121. data/ext/search.c +1864 -0
  122. data/ext/search.h +953 -0
  123. data/ext/similarity.c +151 -0
  124. data/ext/similarity.h +89 -0
  125. data/ext/sort.c +786 -0
  126. data/ext/stem_ISO_8859_1_danish.h +16 -0
  127. data/ext/stem_ISO_8859_1_dutch.h +16 -0
  128. data/ext/stem_ISO_8859_1_english.h +16 -0
  129. data/ext/stem_ISO_8859_1_finnish.h +16 -0
  130. data/ext/stem_ISO_8859_1_french.h +16 -0
  131. data/ext/stem_ISO_8859_1_german.h +16 -0
  132. data/ext/stem_ISO_8859_1_hungarian.h +16 -0
  133. data/ext/stem_ISO_8859_1_italian.h +16 -0
  134. data/ext/stem_ISO_8859_1_norwegian.h +16 -0
  135. data/ext/stem_ISO_8859_1_porter.h +16 -0
  136. data/ext/stem_ISO_8859_1_portuguese.h +16 -0
  137. data/ext/stem_ISO_8859_1_spanish.h +16 -0
  138. data/ext/stem_ISO_8859_1_swedish.h +16 -0
  139. data/ext/stem_ISO_8859_2_romanian.h +16 -0
  140. data/ext/stem_KOI8_R_russian.h +16 -0
  141. data/ext/stem_UTF_8_danish.h +16 -0
  142. data/ext/stem_UTF_8_dutch.h +16 -0
  143. data/ext/stem_UTF_8_english.h +16 -0
  144. data/ext/stem_UTF_8_finnish.h +16 -0
  145. data/ext/stem_UTF_8_french.h +16 -0
  146. data/ext/stem_UTF_8_german.h +16 -0
  147. data/ext/stem_UTF_8_hungarian.h +16 -0
  148. data/ext/stem_UTF_8_italian.h +16 -0
  149. data/ext/stem_UTF_8_norwegian.h +16 -0
  150. data/ext/stem_UTF_8_porter.h +16 -0
  151. data/ext/stem_UTF_8_portuguese.h +16 -0
  152. data/ext/stem_UTF_8_romanian.h +16 -0
  153. data/ext/stem_UTF_8_russian.h +16 -0
  154. data/ext/stem_UTF_8_spanish.h +16 -0
  155. data/ext/stem_UTF_8_swedish.h +16 -0
  156. data/ext/stem_UTF_8_turkish.h +16 -0
  157. data/ext/stopwords.c +410 -0
  158. data/ext/store.c +698 -0
  159. data/ext/store.h +799 -0
  160. data/ext/symbol.c +10 -0
  161. data/ext/symbol.h +23 -0
  162. data/ext/term_vectors.c +73 -0
  163. data/ext/threading.h +31 -0
  164. data/ext/win32.h +62 -0
  165. data/lib/ferret.rb +30 -0
  166. data/lib/ferret/browser.rb +246 -0
  167. data/lib/ferret/browser/s/global.js +192 -0
  168. data/lib/ferret/browser/s/style.css +148 -0
  169. data/lib/ferret/browser/views/document/list.rhtml +49 -0
  170. data/lib/ferret/browser/views/document/show.rhtml +27 -0
  171. data/lib/ferret/browser/views/error/index.rhtml +7 -0
  172. data/lib/ferret/browser/views/help/index.rhtml +8 -0
  173. data/lib/ferret/browser/views/home/index.rhtml +29 -0
  174. data/lib/ferret/browser/views/layout.rhtml +22 -0
  175. data/lib/ferret/browser/views/term-vector/index.rhtml +4 -0
  176. data/lib/ferret/browser/views/term/index.rhtml +199 -0
  177. data/lib/ferret/browser/views/term/termdocs.rhtml +1 -0
  178. data/lib/ferret/browser/webrick.rb +14 -0
  179. data/lib/ferret/document.rb +130 -0
  180. data/lib/ferret/field_infos.rb +44 -0
  181. data/lib/ferret/field_symbol.rb +87 -0
  182. data/lib/ferret/index.rb +973 -0
  183. data/lib/ferret/number_tools.rb +157 -0
  184. data/lib/ferret/version.rb +3 -0
  185. data/setup.rb +1555 -0
  186. data/test/long_running/largefile/tc_largefile.rb +46 -0
  187. data/test/test_all.rb +5 -0
  188. data/test/test_helper.rb +29 -0
  189. data/test/test_installed.rb +1 -0
  190. data/test/threading/number_to_spoken.rb +132 -0
  191. data/test/threading/thread_safety_index_test.rb +88 -0
  192. data/test/threading/thread_safety_read_write_test.rb +73 -0
  193. data/test/threading/thread_safety_test.rb +133 -0
  194. data/test/unit/analysis/tc_analyzer.rb +550 -0
  195. data/test/unit/analysis/tc_token_stream.rb +653 -0
  196. data/test/unit/index/tc_index.rb +867 -0
  197. data/test/unit/index/tc_index_reader.rb +699 -0
  198. data/test/unit/index/tc_index_writer.rb +447 -0
  199. data/test/unit/index/th_doc.rb +332 -0
  200. data/test/unit/query_parser/tc_query_parser.rb +238 -0
  201. data/test/unit/search/tc_filter.rb +156 -0
  202. data/test/unit/search/tc_fuzzy_query.rb +147 -0
  203. data/test/unit/search/tc_index_searcher.rb +67 -0
  204. data/test/unit/search/tc_multi_searcher.rb +128 -0
  205. data/test/unit/search/tc_multiple_search_requests.rb +58 -0
  206. data/test/unit/search/tc_search_and_sort.rb +179 -0
  207. data/test/unit/search/tc_sort.rb +49 -0
  208. data/test/unit/search/tc_sort_field.rb +27 -0
  209. data/test/unit/search/tc_spans.rb +190 -0
  210. data/test/unit/search/tm_searcher.rb +436 -0
  211. data/test/unit/store/tc_fs_store.rb +115 -0
  212. data/test/unit/store/tc_ram_store.rb +35 -0
  213. data/test/unit/store/tm_store.rb +34 -0
  214. data/test/unit/store/tm_store_lock.rb +68 -0
  215. data/test/unit/tc_document.rb +81 -0
  216. data/test/unit/tc_field_symbol.rb +26 -0
  217. data/test/unit/ts_analysis.rb +2 -0
  218. data/test/unit/ts_index.rb +2 -0
  219. data/test/unit/ts_largefile.rb +4 -0
  220. data/test/unit/ts_query_parser.rb +2 -0
  221. data/test/unit/ts_search.rb +2 -0
  222. data/test/unit/ts_store.rb +2 -0
  223. data/test/unit/ts_utils.rb +2 -0
  224. data/test/unit/utils/tc_bit_vector.rb +295 -0
  225. data/test/unit/utils/tc_number_tools.rb +117 -0
  226. data/test/unit/utils/tc_priority_queue.rb +106 -0
  227. data/test/utils/content_generator.rb +226 -0
  228. metadata +319 -0
data/ext/global.c ADDED
@@ -0,0 +1,458 @@
1
+ #include "global.h"
2
+ #include "symbol.h"
3
+ #include "hash.h"
4
+ #include <stdarg.h>
5
+ #include <stdio.h>
6
+ #include <string.h>
7
+ #include <errno.h>
8
+ #include <assert.h>
9
+ #include <math.h>
10
+ #include <ctype.h>
11
+ #include <sys/types.h>
12
+ #include <unistd.h>
13
+ #include <signal.h>
14
+ #include "internal.h"
15
+
16
+ const char *EMPTY_STRING = "";
17
+
18
+ bool x_do_logging = false;
19
+ bool x_abort_on_exception = true;
20
+ bool x_has_aborted = false;
21
+ FILE *x_exception_stream = NULL;
22
+
23
+ INLINE int min3(int a, int b, int c)
24
+ {
25
+ return MIN3(a, b, c);
26
+ }
27
+
28
+ INLINE int min2(int a, int b)
29
+ {
30
+ return MIN(a, b);
31
+ }
32
+
33
+ INLINE int max3(int a, int b, int c)
34
+ {
35
+ return MAX3(a, b, c);
36
+ }
37
+
38
+ INLINE int max2(int a, int b)
39
+ {
40
+ return MAX(a, b);
41
+ }
42
+
43
+ int scmp(const void *p1, const void *p2)
44
+ {
45
+ return strcmp(*(char **) p1, *(char **) p2);
46
+ }
47
+
48
+ void frt_strsort(char **str_array, int size)
49
+ {
50
+ qsort(str_array, size, sizeof(char *), &scmp);
51
+ }
52
+
53
+ int icmp(const void *p1, const void *p2)
54
+ {
55
+ int i1 = *(int *) p1;
56
+ int i2 = *(int *) p2;
57
+
58
+ if (i1 > i2) {
59
+ return 1;
60
+ }
61
+ else if (i1 < i2) {
62
+ return -1;
63
+ }
64
+ return 0;
65
+ }
66
+
67
+ int icmp_risky(const void *p1, const void *p2)
68
+ {
69
+ return (*(int *)p1) - *((int *)p2);
70
+ }
71
+
72
+ unsigned int *imalloc(unsigned int value)
73
+ {
74
+ unsigned int *p = ALLOC(unsigned int);
75
+ *p = value;
76
+ return p;
77
+ }
78
+
79
+ unsigned long *lmalloc(unsigned long value)
80
+ {
81
+ unsigned long *p = ALLOC(unsigned long);
82
+ *p = value;
83
+ return p;
84
+ }
85
+
86
+ u32 *u32malloc(u32 value)
87
+ {
88
+ u32 *p = ALLOC(u32);
89
+ *p = value;
90
+ return p;
91
+ }
92
+
93
+ u64 *u64malloc(u64 value)
94
+ {
95
+ u64 *p = ALLOC(u64);
96
+ *p = value;
97
+ return p;
98
+ }
99
+
100
+ /* concatenate two strings freeing the second */
101
+ char *estrcat(char *str1, char *str2)
102
+ {
103
+ size_t len1 = strlen(str1);
104
+ size_t len2 = strlen(str2);
105
+ REALLOC_N(str1, char, len1 + len2 + 3); /* leave room for <CR> */
106
+ memcpy(str1 + len1, str2, len2 + 1); /* make sure '\0' copied too */
107
+ free(str2);
108
+ return str1;
109
+ }
110
+
111
+ /* epstrdup: duplicate a string with a format, report if error */
112
+ char *epstrdup(const char *fmt, int len, ...)
113
+ {
114
+ char *string;
115
+ va_list args;
116
+ len += (int) strlen(fmt);
117
+
118
+ string = ALLOC_N(char, len + 1);
119
+ va_start(args, len);
120
+ vsprintf(string, fmt, args);
121
+ va_end(args);
122
+
123
+ return string;
124
+ }
125
+
126
+ /* estrdup: duplicate a string, report if error */
127
+ char *estrdup(const char *s)
128
+ {
129
+ char *t = ALLOC_N(char, strlen(s) + 1);
130
+ strcpy(t, s);
131
+ return t;
132
+ }
133
+
134
+ /* Pretty print a float to the buffer. The buffer should have at least 32
135
+ * bytes available.
136
+ */
137
+ char *dbl_to_s(char *buf, double num)
138
+ {
139
+ char *p, *e;
140
+
141
+ #ifdef FRT_IS_C99
142
+ if (isinf(num)) {
143
+ return estrdup(num < 0 ? "-Infinity" : "Infinity");
144
+ }
145
+ else if (isnan(num)) {
146
+ return estrdup("NaN");
147
+ }
148
+ #endif
149
+
150
+ sprintf(buf, "%#.7g", num);
151
+ if (!(e = strchr(buf, 'e'))) {
152
+ e = buf + strlen(buf);
153
+ }
154
+ if (!isdigit(e[-1])) {
155
+ /* reformat if ended with decimal point (ex 111111111111111.) */
156
+ sprintf(buf, "%#.6e", num);
157
+ if (!(e = strchr(buf, 'e'))) {
158
+ e = buf + strlen(buf);
159
+ }
160
+ }
161
+ p = e;
162
+ while (p[-1] == '0' && isdigit(p[-2])) {
163
+ p--;
164
+ }
165
+
166
+ memmove(p, e, strlen(e) + 1);
167
+ return buf;
168
+ }
169
+
170
+ /* strfmt: like sprintf except that it allocates memory for the string */
171
+ char *vstrfmt(const char *fmt, va_list args)
172
+ {
173
+ char *string;
174
+ char *p = (char *) fmt, *q;
175
+ int len = (int) strlen(fmt) + 1;
176
+ int slen, curlen;
177
+ char *s;
178
+ long l;
179
+ double d;
180
+
181
+ q = string = ALLOC_N(char, len);
182
+
183
+ while (*p) {
184
+ if (*p == '%') {
185
+ p++;
186
+ switch (*p) {
187
+ case 's':
188
+ p++;
189
+ s = va_arg(args, char *);
190
+ /* to be consistent with printf print (null) for NULL */
191
+ if (!s) {
192
+ s = "(null)";
193
+ }
194
+ slen = (int) strlen(s);
195
+ len += slen;
196
+ curlen = q - string;
197
+ REALLOC_N(string, char, len);
198
+ q = string + curlen;
199
+ memcpy(q, s, slen);
200
+ q += slen;
201
+ continue;
202
+ case 'f':
203
+ p++;
204
+ len += 32;
205
+ *q = 0;
206
+ REALLOC_N(string, char, len);
207
+ q = string + strlen(string);
208
+ d = va_arg(args, double);
209
+ dbl_to_s(q, d);
210
+ q += strlen(q);
211
+ continue;
212
+ case 'd':
213
+ p++;
214
+ len += 20;
215
+ *q = 0;
216
+ REALLOC_N(string, char, len);
217
+ q = string + strlen(string);
218
+ l = va_arg(args, long);
219
+ q += sprintf(q, "%ld", l);
220
+ continue;
221
+ default:
222
+ break;
223
+ }
224
+ }
225
+ *q = *p;
226
+ p++;
227
+ q++;
228
+ }
229
+ *q = 0;
230
+
231
+ return string;
232
+ }
233
+
234
+ char *strfmt(const char *fmt, ...)
235
+ {
236
+ va_list args;
237
+ char *str;
238
+ va_start(args, fmt);
239
+ str = vstrfmt(fmt, args);
240
+ va_end(args);
241
+ return str;
242
+ }
243
+
244
+ void dummy_free(void *p)
245
+ {
246
+ (void)p; /* suppress unused argument warning */
247
+ }
248
+
249
+ #ifdef HAVE_GDB
250
+ #define CMD_BUF_SIZE (128 + FILENAME_MAX)
251
+ /* need to declare this as it is masked by default in linux */
252
+
253
+ static char *build_shell_command(const char *gdb_filename)
254
+ {
255
+ int pid = getpid();
256
+ char *buf = ALLOC_N(char, CMD_BUF_SIZE);
257
+ char *command =
258
+ "gdb -quiet -command=%s %s %d 2>/dev/null | grep '^[ #]'";
259
+
260
+ snprintf(buf, CMD_BUF_SIZE, command, gdb_filename, progname(), pid);
261
+ return buf;
262
+ }
263
+
264
+ /* Returns the fd to the tempfile */
265
+ static int build_tempfile(char *name, size_t max_size)
266
+ {
267
+ char *tmpdir = getenv("TMPDIR");
268
+
269
+ snprintf(name, max_size, "%s/frt.XXXXXXXXXX", tmpdir ? tmpdir : "/tmp");
270
+ return mkstemp(name);
271
+ }
272
+
273
+ static char *build_gdb_commandfile()
274
+ {
275
+ const char *commands = "bt\nquit\n";
276
+ char *filename = ALLOC_N(char, FILENAME_MAX);
277
+ int fd = build_tempfile(filename, FILENAME_MAX);
278
+ if (fd < 0)
279
+ return NULL;
280
+ write(fd, commands, strlen(commands));
281
+ close(fd);
282
+ return filename;
283
+ }
284
+ #endif
285
+
286
+ /**
287
+ * Call out to gdb to get our stacktrace.
288
+ */
289
+ char *get_stacktrace()
290
+ {
291
+ #ifdef HAVE_GDB
292
+ FILE *stream;
293
+ char *gdb_filename = NULL, *buf = NULL, *stack = NULL;
294
+ int offset = -BUFFER_SIZE;
295
+
296
+ if ( !(gdb_filename = build_gdb_commandfile()) ) {
297
+ fprintf(EXCEPTION_STREAM,
298
+ "Unable to build gdb command file\n");
299
+ goto cleanup;
300
+ }
301
+ if ( !(buf = build_shell_command(gdb_filename)) ) {
302
+ fprintf(EXCEPTION_STREAM,
303
+ "Unable to build stacktrace shell command\n");
304
+ goto cleanup;
305
+ }
306
+
307
+ if ( !(stream = popen(buf, "r")) ) {
308
+ fprintf(EXCEPTION_STREAM,
309
+ "Unable to exec stacktrace shell command: '%s'\n", buf);
310
+ goto cleanup;
311
+ }
312
+
313
+ do {
314
+ offset += BUFFER_SIZE;
315
+ REALLOC_N(stack, char, offset + BUFFER_SIZE);
316
+ ZEROSET_N(stack + offset, char, BUFFER_SIZE);
317
+ } while(fread(stack + offset, 1, BUFFER_SIZE, stream) == BUFFER_SIZE);
318
+
319
+ pclose(stream);
320
+
321
+ cleanup:
322
+ if (gdb_filename) free(gdb_filename);
323
+ if (buf) free(buf);
324
+ return stack;
325
+ #else
326
+ return NULL;
327
+ #endif
328
+ }
329
+
330
+ void print_stacktrace()
331
+ {
332
+ char *stack = get_stacktrace();
333
+
334
+ fprintf(EXCEPTION_STREAM, "Stack trace:\n%s",
335
+ stack ? stack : "Not available\n");
336
+ if (stack) free(stack);
337
+ }
338
+
339
+ typedef struct FreeMe
340
+ {
341
+ void *p;
342
+ free_ft free_func;
343
+ } FreeMe;
344
+
345
+ static FreeMe *free_mes = NULL;
346
+ static int free_mes_size = 0;
347
+ static int free_mes_capa = 0;
348
+
349
+ void register_for_cleanup(void *p, free_ft free_func)
350
+ {
351
+ FreeMe *free_me;
352
+ if (free_mes_capa == 0) {
353
+ free_mes_capa = 16;
354
+ free_mes = ALLOC_N(FreeMe, free_mes_capa);
355
+ }
356
+ else if (free_mes_capa <= free_mes_size) {
357
+ free_mes_capa *= 2;
358
+ REALLOC_N(free_mes, FreeMe, free_mes_capa);
359
+ }
360
+ free_me = free_mes + free_mes_size++;
361
+ free_me->p = p;
362
+ free_me->free_func = free_func;
363
+ }
364
+
365
+ void clean_up()
366
+ {
367
+ int i;
368
+ for (i = 0; i < free_mes_size; i++) {
369
+ FreeMe *free_me = free_mes + i;
370
+ free_me->free_func(free_me->p);
371
+ }
372
+ free(free_mes);
373
+ free_mes = NULL;
374
+ free_mes_size = free_mes_capa = 0;
375
+ }
376
+
377
+ /* weprintf: print error message and don't exit */
378
+ void weprintf(const char *fmt, ...)
379
+ {
380
+ va_list args;
381
+
382
+ fflush(stdout);
383
+ fprintf(stderr, "%s: ", progname());
384
+
385
+ va_start(args, fmt);
386
+ vfprintf(stderr, fmt, args);
387
+ va_end(args);
388
+
389
+ if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':')
390
+ fprintf(stderr, " %s", strerror(errno));
391
+ fprintf(stderr, "\n");
392
+ }
393
+
394
+ #define MAX_PROG_NAME 200
395
+ static char name[MAX_PROG_NAME]; /* program name for error msgs */
396
+
397
+ /* setprogname: set stored name of program */
398
+ void setprogname(const char *str)
399
+ {
400
+ strncpy(name, str, sizeof(name) - 1);
401
+ }
402
+
403
+ const char *progname()
404
+ {
405
+ return name;
406
+ }
407
+
408
+ static const char *signal_to_string(int signum)
409
+ {
410
+ switch (signum)
411
+ {
412
+ case SIGILL: return "SIGILL";
413
+ case SIGABRT: return "SIGABRT";
414
+ case SIGFPE: return "SIGFPE";
415
+ case SIGBUS: return "SIGBUS";
416
+ case SIGSEGV: return "SIGSEGV";
417
+ }
418
+
419
+ return "Unknown Signal";
420
+ }
421
+
422
+ static void sighandler_crash(int signum)
423
+ {
424
+ print_stacktrace();
425
+ XEXIT("Exiting on signal %s (%d)",
426
+ signal_to_string(signum), signum);
427
+ }
428
+
429
+ #define SETSIG_IF_UNSET(sig, new) do { \
430
+ struct sigaction __old; \
431
+ sigaction(sig, NULL, &__old); \
432
+ if (__old.sa_handler != SIG_IGN) { \
433
+ sigaction(sig, &new, NULL); \
434
+ } \
435
+ } while(0)
436
+
437
+ void init(int argc, const char *const argv[])
438
+ {
439
+ struct sigaction action;
440
+
441
+ if (argc > 0) {
442
+ setprogname(argv[0]);
443
+ }
444
+
445
+ action.sa_handler = sighandler_crash;
446
+ sigemptyset(&action.sa_mask);
447
+ action.sa_flags = 0;
448
+
449
+ SETSIG_IF_UNSET(SIGILL , action);
450
+ SETSIG_IF_UNSET(SIGABRT, action);
451
+ SETSIG_IF_UNSET(SIGFPE , action);
452
+ SETSIG_IF_UNSET(SIGBUS , action);
453
+ SETSIG_IF_UNSET(SIGSEGV, action);
454
+
455
+ symbol_init();
456
+
457
+ atexit(&hash_finalize);
458
+ }