ferret 0.11.6 → 0.11.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. data/README +10 -22
  2. data/RELEASE_CHANGES +137 -0
  3. data/RELEASE_NOTES +60 -0
  4. data/Rakefile +379 -274
  5. data/TODO +100 -8
  6. data/bin/ferret-browser +0 -0
  7. data/ext/BZLIB_blocksort.c +1094 -0
  8. data/ext/BZLIB_bzlib.c +1578 -0
  9. data/ext/BZLIB_compress.c +672 -0
  10. data/ext/BZLIB_crctable.c +104 -0
  11. data/ext/BZLIB_decompress.c +626 -0
  12. data/ext/BZLIB_huffman.c +205 -0
  13. data/ext/BZLIB_randtable.c +84 -0
  14. data/ext/{api.c → STEMMER_api.c} +7 -10
  15. data/ext/{libstemmer.c → STEMMER_libstemmer.c} +3 -2
  16. data/ext/{stem_ISO_8859_1_danish.c → STEMMER_stem_ISO_8859_1_danish.c} +123 -124
  17. data/ext/{stem_ISO_8859_1_dutch.c → STEMMER_stem_ISO_8859_1_dutch.c} +177 -188
  18. data/ext/STEMMER_stem_ISO_8859_1_english.c +1117 -0
  19. data/ext/{stem_ISO_8859_1_finnish.c → STEMMER_stem_ISO_8859_1_finnish.c} +276 -306
  20. data/ext/STEMMER_stem_ISO_8859_1_french.c +1246 -0
  21. data/ext/{stem_ISO_8859_1_german.c → STEMMER_stem_ISO_8859_1_german.c} +161 -170
  22. data/ext/STEMMER_stem_ISO_8859_1_hungarian.c +1230 -0
  23. data/ext/STEMMER_stem_ISO_8859_1_italian.c +1065 -0
  24. data/ext/STEMMER_stem_ISO_8859_1_norwegian.c +297 -0
  25. data/ext/{stem_ISO_8859_1_porter.c → STEMMER_stem_ISO_8859_1_porter.c} +263 -290
  26. data/ext/{stem_ISO_8859_1_portuguese.c → STEMMER_stem_ISO_8859_1_portuguese.c} +362 -380
  27. data/ext/STEMMER_stem_ISO_8859_1_spanish.c +1093 -0
  28. data/ext/STEMMER_stem_ISO_8859_1_swedish.c +307 -0
  29. data/ext/STEMMER_stem_ISO_8859_2_romanian.c +998 -0
  30. data/ext/{stem_KOI8_R_russian.c → STEMMER_stem_KOI8_R_russian.c} +244 -245
  31. data/ext/STEMMER_stem_UTF_8_danish.c +339 -0
  32. data/ext/{stem_UTF_8_dutch.c → STEMMER_stem_UTF_8_dutch.c} +192 -211
  33. data/ext/STEMMER_stem_UTF_8_english.c +1125 -0
  34. data/ext/{stem_UTF_8_finnish.c → STEMMER_stem_UTF_8_finnish.c} +284 -324
  35. data/ext/STEMMER_stem_UTF_8_french.c +1256 -0
  36. data/ext/{stem_UTF_8_german.c → STEMMER_stem_UTF_8_german.c} +170 -187
  37. data/ext/STEMMER_stem_UTF_8_hungarian.c +1234 -0
  38. data/ext/STEMMER_stem_UTF_8_italian.c +1073 -0
  39. data/ext/STEMMER_stem_UTF_8_norwegian.c +299 -0
  40. data/ext/{stem_UTF_8_porter.c → STEMMER_stem_UTF_8_porter.c} +271 -310
  41. data/ext/STEMMER_stem_UTF_8_portuguese.c +1023 -0
  42. data/ext/STEMMER_stem_UTF_8_romanian.c +1004 -0
  43. data/ext/STEMMER_stem_UTF_8_russian.c +694 -0
  44. data/ext/STEMMER_stem_UTF_8_spanish.c +1097 -0
  45. data/ext/STEMMER_stem_UTF_8_swedish.c +309 -0
  46. data/ext/STEMMER_stem_UTF_8_turkish.c +2205 -0
  47. data/ext/{utilities.c → STEMMER_utilities.c} +100 -68
  48. data/ext/analysis.c +276 -121
  49. data/ext/analysis.h +190 -143
  50. data/ext/api.h +3 -4
  51. data/ext/array.c +5 -3
  52. data/ext/array.h +52 -43
  53. data/ext/bitvector.c +38 -482
  54. data/ext/bitvector.h +446 -124
  55. data/ext/bzlib.h +282 -0
  56. data/ext/bzlib_private.h +503 -0
  57. data/ext/compound_io.c +23 -22
  58. data/ext/config.h +21 -11
  59. data/ext/document.c +43 -40
  60. data/ext/document.h +31 -21
  61. data/ext/except.c +20 -38
  62. data/ext/except.h +89 -76
  63. data/ext/extconf.rb +3 -2
  64. data/ext/ferret.c +49 -35
  65. data/ext/ferret.h +14 -11
  66. data/ext/field_index.c +262 -0
  67. data/ext/field_index.h +52 -0
  68. data/ext/filter.c +11 -10
  69. data/ext/fs_store.c +65 -47
  70. data/ext/global.c +245 -165
  71. data/ext/global.h +252 -54
  72. data/ext/hash.c +200 -243
  73. data/ext/hash.h +205 -163
  74. data/ext/hashset.c +118 -96
  75. data/ext/hashset.h +110 -82
  76. data/ext/header.h +19 -19
  77. data/ext/helper.c +11 -10
  78. data/ext/helper.h +14 -6
  79. data/ext/index.c +745 -366
  80. data/ext/index.h +503 -529
  81. data/ext/internal.h +1020 -0
  82. data/ext/lang.c +10 -0
  83. data/ext/lang.h +35 -15
  84. data/ext/mempool.c +5 -4
  85. data/ext/mempool.h +30 -22
  86. data/ext/modules.h +35 -7
  87. data/ext/multimapper.c +43 -2
  88. data/ext/multimapper.h +32 -23
  89. data/ext/posh.c +0 -0
  90. data/ext/posh.h +4 -38
  91. data/ext/priorityqueue.c +10 -12
  92. data/ext/priorityqueue.h +33 -21
  93. data/ext/q_boolean.c +22 -9
  94. data/ext/q_const_score.c +3 -2
  95. data/ext/q_filtered_query.c +15 -12
  96. data/ext/q_fuzzy.c +147 -135
  97. data/ext/q_match_all.c +3 -2
  98. data/ext/q_multi_term.c +28 -32
  99. data/ext/q_parser.c +451 -173
  100. data/ext/q_phrase.c +158 -79
  101. data/ext/q_prefix.c +16 -18
  102. data/ext/q_range.c +363 -31
  103. data/ext/q_span.c +130 -141
  104. data/ext/q_term.c +21 -21
  105. data/ext/q_wildcard.c +19 -23
  106. data/ext/r_analysis.c +369 -242
  107. data/ext/r_index.c +421 -434
  108. data/ext/r_qparser.c +142 -92
  109. data/ext/r_search.c +790 -407
  110. data/ext/r_store.c +44 -44
  111. data/ext/r_utils.c +264 -96
  112. data/ext/ram_store.c +29 -23
  113. data/ext/scanner.c +895 -0
  114. data/ext/scanner.h +36 -0
  115. data/ext/scanner_mb.c +6701 -0
  116. data/ext/scanner_utf8.c +4415 -0
  117. data/ext/search.c +210 -87
  118. data/ext/search.h +556 -488
  119. data/ext/similarity.c +17 -16
  120. data/ext/similarity.h +51 -44
  121. data/ext/sort.c +157 -354
  122. data/ext/stem_ISO_8859_1_hungarian.h +16 -0
  123. data/ext/stem_ISO_8859_2_romanian.h +16 -0
  124. data/ext/stem_UTF_8_hungarian.h +16 -0
  125. data/ext/stem_UTF_8_romanian.h +16 -0
  126. data/ext/stem_UTF_8_turkish.h +16 -0
  127. data/ext/stopwords.c +287 -278
  128. data/ext/store.c +57 -51
  129. data/ext/store.h +308 -286
  130. data/ext/symbol.c +10 -0
  131. data/ext/symbol.h +23 -0
  132. data/ext/term_vectors.c +14 -293
  133. data/ext/threading.h +22 -22
  134. data/ext/win32.h +12 -4
  135. data/lib/ferret.rb +2 -1
  136. data/lib/ferret/browser.rb +1 -1
  137. data/lib/ferret/field_symbol.rb +94 -0
  138. data/lib/ferret/index.rb +221 -34
  139. data/lib/ferret/number_tools.rb +6 -6
  140. data/lib/ferret/version.rb +3 -0
  141. data/test/{unit → long_running}/largefile/tc_largefile.rb +1 -1
  142. data/test/test_helper.rb +7 -2
  143. data/test/test_installed.rb +1 -0
  144. data/test/threading/thread_safety_index_test.rb +10 -1
  145. data/test/threading/thread_safety_read_write_test.rb +4 -7
  146. data/test/threading/thread_safety_test.rb +0 -0
  147. data/test/unit/analysis/tc_analyzer.rb +29 -27
  148. data/test/unit/analysis/tc_token_stream.rb +23 -16
  149. data/test/unit/index/tc_index.rb +116 -11
  150. data/test/unit/index/tc_index_reader.rb +27 -27
  151. data/test/unit/index/tc_index_writer.rb +10 -0
  152. data/test/unit/index/th_doc.rb +38 -21
  153. data/test/unit/search/tc_filter.rb +31 -10
  154. data/test/unit/search/tc_index_searcher.rb +6 -0
  155. data/test/unit/search/tm_searcher.rb +53 -1
  156. data/test/unit/store/tc_fs_store.rb +40 -2
  157. data/test/unit/store/tc_ram_store.rb +0 -0
  158. data/test/unit/store/tm_store.rb +0 -0
  159. data/test/unit/store/tm_store_lock.rb +7 -6
  160. data/test/unit/tc_field_symbol.rb +26 -0
  161. data/test/unit/ts_analysis.rb +0 -0
  162. data/test/unit/ts_index.rb +0 -0
  163. data/test/unit/ts_store.rb +0 -0
  164. data/test/unit/ts_utils.rb +0 -0
  165. data/test/unit/utils/tc_number_tools.rb +0 -0
  166. data/test/utils/content_generator.rb +226 -0
  167. metadata +262 -221
  168. data/ext/inc/lang.h +0 -48
  169. data/ext/inc/threading.h +0 -31
  170. data/ext/stem_ISO_8859_1_english.c +0 -1156
  171. data/ext/stem_ISO_8859_1_french.c +0 -1276
  172. data/ext/stem_ISO_8859_1_italian.c +0 -1091
  173. data/ext/stem_ISO_8859_1_norwegian.c +0 -296
  174. data/ext/stem_ISO_8859_1_spanish.c +0 -1119
  175. data/ext/stem_ISO_8859_1_swedish.c +0 -307
  176. data/ext/stem_UTF_8_danish.c +0 -344
  177. data/ext/stem_UTF_8_english.c +0 -1176
  178. data/ext/stem_UTF_8_french.c +0 -1296
  179. data/ext/stem_UTF_8_italian.c +0 -1113
  180. data/ext/stem_UTF_8_norwegian.c +0 -302
  181. data/ext/stem_UTF_8_portuguese.c +0 -1055
  182. data/ext/stem_UTF_8_russian.c +0 -709
  183. data/ext/stem_UTF_8_spanish.c +0 -1137
  184. data/ext/stem_UTF_8_swedish.c +0 -313
  185. data/lib/ferret_version.rb +0 -3
@@ -1,4 +1,6 @@
1
1
  #include "global.h"
2
+ #include "symbol.h"
3
+ #include "hash.h"
2
4
  #include <stdarg.h>
3
5
  #include <stdio.h>
4
6
  #include <string.h>
@@ -6,10 +8,17 @@
6
8
  #include <assert.h>
7
9
  #include <math.h>
8
10
  #include <ctype.h>
11
+ #include <sys/types.h>
12
+ #include <unistd.h>
13
+ #include <signal.h>
14
+ #include "internal.h"
9
15
 
10
16
  const char *EMPTY_STRING = "";
11
17
 
12
- bool x_do_logging = false;
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;
13
22
 
14
23
  INLINE int min3(int a, int b, int c)
15
24
  {
@@ -36,6 +45,11 @@ int scmp(const void *p1, const void *p2)
36
45
  return strcmp(*(char **) p1, *(char **) p2);
37
46
  }
38
47
 
48
+ void frt_strsort(char **str_array, int size)
49
+ {
50
+ qsort(str_array, size, sizeof(char *), &scmp);
51
+ }
52
+
39
53
  int icmp(const void *p1, const void *p2)
40
54
  {
41
55
  int i1 = *(int *) p1;
@@ -69,104 +83,20 @@ unsigned long *lmalloc(unsigned long value)
69
83
  return p;
70
84
  }
71
85
 
72
- f_u32 *u32malloc(f_u32 value)
86
+ u32 *u32malloc(u32 value)
73
87
  {
74
- f_u32 *p = ALLOC(f_u32);
88
+ u32 *p = ALLOC(u32);
75
89
  *p = value;
76
90
  return p;
77
91
  }
78
92
 
79
- f_u64 *u64malloc(f_u64 value)
93
+ u64 *u64malloc(u64 value)
80
94
  {
81
- f_u64 *p = ALLOC(f_u64);
95
+ u64 *p = ALLOC(u64);
82
96
  *p = value;
83
97
  return p;
84
98
  }
85
99
 
86
-
87
- #ifndef RUBY_BINDINGS
88
- /* frt_exit: print error message and exit */
89
- # ifdef FRT_HAS_VARARGS
90
- void vfrt_exit(const char *file, int line_num, const char *func,
91
- const char *err_type, const char *fmt, va_list args)
92
- # else
93
- void V_FRT_EXIT(const char *err_type, const char *fmt, va_list args)
94
- # endif
95
- {
96
- fflush(stdout);
97
- fprintf(stderr, "\n");
98
- if (progname() != NULL) {
99
- fprintf(stderr, "%s: ", progname());
100
- }
101
-
102
- # ifdef FRT_HAS_VARARGS
103
- fprintf(stderr, "%s occured at <%s>:%d in %s\n",
104
- err_type, file, line_num, func);
105
- # else
106
- fprintf(stderr, "%s occured:\n", err_type);
107
- # endif
108
- vfprintf(stderr, fmt, args);
109
-
110
- if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') {
111
- fprintf(stderr, " %s", strerror(errno));
112
- }
113
-
114
- fprintf(stderr, "\n");
115
- exit(2); /* conventional value for failed execution */
116
- }
117
-
118
-
119
- # ifdef FRT_HAS_VARARGS
120
- void frt_exit(const char *file, int line_num, const char *func,
121
- const char *err_type, const char *fmt, ...)
122
- # else
123
- void FRT_EXIT(const char *err_type, const char *fmt, ...)
124
- # endif
125
- {
126
- va_list args;
127
- va_start(args, fmt);
128
- # ifdef FRT_HAS_VARARGS
129
- vfrt_exit(file, line_num, func, err_type, fmt, args);
130
- # else
131
- V_FRT_EXIT(err_type, fmt, args);
132
- # endif
133
- va_end(args);
134
- }
135
- #endif
136
-
137
-
138
- /* weprintf: print error message and don't exit */
139
- void weprintf(const char *fmt, ...)
140
- {
141
- va_list args;
142
-
143
- fflush(stdout);
144
- if (progname() != NULL)
145
- fprintf(stderr, "%s: ", progname());
146
-
147
- va_start(args, fmt);
148
- vfprintf(stderr, fmt, args);
149
- va_end(args);
150
-
151
- if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':')
152
- fprintf(stderr, " %s", strerror(errno));
153
- fprintf(stderr, "\n");
154
- }
155
-
156
- #define MAX_PROG_NAME 200
157
- static char name[MAX_PROG_NAME]; /* program name for error msgs */
158
-
159
- /* setprogname: set stored name of program */
160
- void setprogname(const char *str)
161
- {
162
- strncpy(name, str, MAX_PROG_NAME - 1);
163
- }
164
-
165
- char *progname()
166
- {
167
- return name;
168
- }
169
-
170
100
  /* concatenate two strings freeing the second */
171
101
  char *estrcat(char *str1, char *str2)
172
102
  {
@@ -196,52 +126,11 @@ char *epstrdup(const char *fmt, int len, ...)
196
126
  /* estrdup: duplicate a string, report if error */
197
127
  char *estrdup(const char *s)
198
128
  {
199
- char *t = (char *)malloc(strlen(s) + 1);
200
-
201
- if (t == NULL) {
202
- RAISE(MEM_ERROR, "failed to allocate %d bytes", (int)strlen(s) + 1);
203
- }
204
-
129
+ char *t = ALLOC_N(char, strlen(s) + 1);
205
130
  strcpy(t, s);
206
131
  return t;
207
132
  }
208
133
 
209
- /* emalloc: malloc and report if error */
210
- void *emalloc(size_t size)
211
- {
212
- void *p = malloc(size);
213
-
214
- if (p == NULL) {
215
- RAISE(MEM_ERROR, "failed to allocate %d bytes", (int)size);
216
- }
217
-
218
- return p;
219
- }
220
-
221
- /* ecalloc: malloc, zeroset and report if error */
222
- void *ecalloc(size_t size)
223
- {
224
- void *p = calloc(1, size);
225
-
226
- if (p == NULL) {
227
- RAISE(MEM_ERROR, "failed to allocate %d bytes", (int)size);
228
- }
229
-
230
- return p;
231
- }
232
-
233
- /* erealloc: realloc and report if error */
234
- void *erealloc(void *ptr, size_t size)
235
- {
236
- void *p = realloc(ptr, size);
237
-
238
- if (p == NULL) {
239
- RAISE(MEM_ERROR, "failed to reallocate %d bytes", (int)size);
240
- }
241
-
242
- return p;
243
- }
244
-
245
134
  /* Pretty print a float to the buffer. The buffer should have at least 32
246
135
  * bytes available.
247
136
  */
@@ -258,16 +147,14 @@ char *dbl_to_s(char *buf, double num)
258
147
  }
259
148
  #endif
260
149
 
261
- sprintf(buf, "%#.7g", num);
150
+ sprintf(buf, DBL2S, num);
262
151
  if (!(e = strchr(buf, 'e'))) {
263
152
  e = buf + strlen(buf);
264
153
  }
265
154
  if (!isdigit(e[-1])) {
266
155
  /* reformat if ended with decimal point (ex 111111111111111.) */
267
156
  sprintf(buf, "%#.6e", num);
268
- if (!(e = strchr(buf, 'e'))) {
269
- e = buf + strlen(buf);
270
- }
157
+ if (!(e = strchr(buf, 'e'))) { e = buf + strlen(buf); }
271
158
  }
272
159
  p = e;
273
160
  while (p[-1] == '0' && isdigit(p[-2])) {
@@ -284,9 +171,9 @@ char *vstrfmt(const char *fmt, va_list args)
284
171
  char *string;
285
172
  char *p = (char *) fmt, *q;
286
173
  int len = (int) strlen(fmt) + 1;
287
- int slen;
174
+ int slen, curlen;
288
175
  char *s;
289
- long i;
176
+ long l;
290
177
  double d;
291
178
 
292
179
  q = string = ALLOC_N(char, len);
@@ -298,15 +185,17 @@ char *vstrfmt(const char *fmt, va_list args)
298
185
  case 's':
299
186
  p++;
300
187
  s = va_arg(args, char *);
301
- if (s) {
302
- slen = (int) strlen(s);
303
- len += slen;
304
- *q = 0;
305
- REALLOC_N(string, char, len);
306
- q = string + strlen(string);
307
- sprintf(q, s);
308
- q += slen;
188
+ /* to be consistent with printf print (null) for NULL */
189
+ if (!s) {
190
+ s = "(null)";
309
191
  }
192
+ slen = (int) strlen(s);
193
+ len += slen;
194
+ curlen = q - string;
195
+ REALLOC_N(string, char, len);
196
+ q = string + curlen;
197
+ memcpy(q, s, slen);
198
+ q += slen;
310
199
  continue;
311
200
  case 'f':
312
201
  p++;
@@ -324,9 +213,8 @@ char *vstrfmt(const char *fmt, va_list args)
324
213
  *q = 0;
325
214
  REALLOC_N(string, char, len);
326
215
  q = string + strlen(string);
327
- i = va_arg(args, long);
328
- sprintf(q, "%ld", i);
329
- q += strlen(q);
216
+ l = va_arg(args, long);
217
+ q += sprintf(q, "%ld", l);
330
218
  continue;
331
219
  default:
332
220
  break;
@@ -356,29 +244,95 @@ void dummy_free(void *p)
356
244
  (void)p; /* suppress unused argument warning */
357
245
  }
358
246
 
359
- #ifdef FRT_IS_C99
360
- extern void usleep(unsigned long usec);
361
- #else
362
- # ifdef RUBY_BINDINGS
363
- struct timeval rb_time_interval _((VALUE));
364
- # else
365
- # include <unistd.h>
366
- # endif
247
+ #ifdef HAVE_GDB
248
+ #define CMD_BUF_SIZE (128 + FILENAME_MAX)
249
+ /* need to declare this as it is masked by default in linux */
250
+
251
+ static char *build_shell_command(const char *gdb_filename)
252
+ {
253
+ int pid = getpid();
254
+ char *buf = ALLOC_N(char, CMD_BUF_SIZE);
255
+ char *command =
256
+ "gdb -quiet -command=%s %s %d 2>/dev/null | grep '^[ #]'";
257
+
258
+ snprintf(buf, CMD_BUF_SIZE, command, gdb_filename, progname(), pid);
259
+ return buf;
260
+ }
261
+
262
+ /* Returns the fd to the tempfile */
263
+ static int build_tempfile(char *name, size_t max_size)
264
+ {
265
+ char *tmpdir = getenv("TMPDIR");
266
+
267
+ snprintf(name, max_size, "%s/frt.XXXXXXXXXX", tmpdir ? tmpdir : "/tmp");
268
+ return mkstemp(name);
269
+ }
270
+
271
+ static char *build_gdb_commandfile()
272
+ {
273
+ const char *commands = "bt\nquit\n";
274
+ char *filename = ALLOC_N(char, FILENAME_MAX);
275
+ int fd = build_tempfile(filename, FILENAME_MAX);
276
+ if (fd < 0) { return NULL; }
277
+ write(fd, commands, strlen(commands));
278
+ close(fd);
279
+ return filename;
280
+ }
367
281
  #endif
368
282
 
369
- extern void micro_sleep(const int micro_seconds)
283
+ /**
284
+ * Call out to gdb to get our stacktrace.
285
+ */
286
+ char *get_stacktrace()
370
287
  {
371
- #ifdef RUBY_BINDINGS
372
- rb_thread_wait_for(rb_time_interval(rb_float_new((double)micro_seconds/1000000.0)));
288
+ #ifdef HAVE_GDB
289
+ FILE *stream;
290
+ char *gdb_filename = NULL, *buf = NULL, *stack = NULL;
291
+ int offset = -BUFFER_SIZE;
292
+
293
+ if ( !(gdb_filename = build_gdb_commandfile()) ) {
294
+ fprintf(EXCEPTION_STREAM,
295
+ "Unable to build gdb command file\n");
296
+ goto cleanup;
297
+ }
298
+ if ( !(buf = build_shell_command(gdb_filename)) ) {
299
+ fprintf(EXCEPTION_STREAM,
300
+ "Unable to build stacktrace shell command\n");
301
+ goto cleanup;
302
+ }
303
+
304
+ if ( !(stream = popen(buf, "r")) ) {
305
+ fprintf(EXCEPTION_STREAM,
306
+ "Unable to exec stacktrace shell command: '%s'\n", buf);
307
+ goto cleanup;
308
+ }
309
+
310
+ do {
311
+ offset += BUFFER_SIZE;
312
+ REALLOC_N(stack, char, offset + BUFFER_SIZE);
313
+ ZEROSET_N(stack + offset, char, BUFFER_SIZE);
314
+ } while(fread(stack + offset, 1, BUFFER_SIZE, stream) == BUFFER_SIZE);
315
+
316
+ pclose(stream);
317
+
318
+ cleanup:
319
+ if (gdb_filename) free(gdb_filename);
320
+ if (buf) free(buf);
321
+ return stack;
373
322
  #else
374
- # ifdef POSH_OS_WIN32
375
- Sleep(micro_seconds / 1000);
376
- # else
377
- usleep(micro_seconds);
378
- # endif
323
+ return NULL;
379
324
  #endif
380
325
  }
381
326
 
327
+ void print_stacktrace()
328
+ {
329
+ char *stack = get_stacktrace();
330
+
331
+ fprintf(EXCEPTION_STREAM, "Stack trace:\n%s",
332
+ stack ? stack : "Not available\n");
333
+ if (stack) free(stack);
334
+ }
335
+
382
336
  typedef struct FreeMe
383
337
  {
384
338
  void *p;
@@ -405,7 +359,7 @@ void register_for_cleanup(void *p, free_ft free_func)
405
359
  free_me->free_func = free_func;
406
360
  }
407
361
 
408
- void do_clean_up()
362
+ void clean_up()
409
363
  {
410
364
  int i;
411
365
  for (i = 0; i < free_mes_size; i++) {
@@ -416,3 +370,129 @@ void do_clean_up()
416
370
  free_mes = NULL;
417
371
  free_mes_size = free_mes_capa = 0;
418
372
  }
373
+
374
+ /* weprintf: print error message and don't exit */
375
+ void weprintf(const char *fmt, ...)
376
+ {
377
+ va_list args;
378
+
379
+ fflush(stdout);
380
+ fprintf(stderr, "%s: ", progname());
381
+
382
+ va_start(args, fmt);
383
+ vfprintf(stderr, fmt, args);
384
+ va_end(args);
385
+
386
+ if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':')
387
+ fprintf(stderr, " %s", strerror(errno));
388
+ fprintf(stderr, "\n");
389
+ }
390
+
391
+ #define MAX_PROG_NAME 200
392
+ static char name[MAX_PROG_NAME]; /* program name for error msgs */
393
+
394
+ /* setprogname: set stored name of program */
395
+ void setprogname(const char *str)
396
+ {
397
+ strncpy(name, str, sizeof(name) - 1);
398
+ }
399
+
400
+ const char *progname()
401
+ {
402
+ return name;
403
+ }
404
+
405
+ static const char *signal_to_string(int signum)
406
+ {
407
+ switch (signum)
408
+ {
409
+ case SIGILL: return "SIGILL";
410
+ case SIGABRT: return "SIGABRT";
411
+ case SIGFPE: return "SIGFPE";
412
+ case SIGBUS: return "SIGBUS";
413
+ case SIGSEGV: return "SIGSEGV";
414
+ }
415
+
416
+ return "Unknown Signal";
417
+ }
418
+
419
+ static void sighandler_crash(int signum)
420
+ {
421
+ print_stacktrace();
422
+ XEXIT("Exiting on signal %s (%d)",
423
+ signal_to_string(signum), signum);
424
+ }
425
+
426
+ #define SETSIG_IF_UNSET(sig, new) do { \
427
+ struct sigaction __old; \
428
+ sigaction(sig, NULL, &__old); \
429
+ if (__old.sa_handler != SIG_IGN) { \
430
+ sigaction(sig, &new, NULL); \
431
+ } \
432
+ } while(0)
433
+
434
+ void init(int argc, const char *const argv[])
435
+ {
436
+ struct sigaction action;
437
+
438
+ if (argc > 0) {
439
+ setprogname(argv[0]);
440
+ }
441
+
442
+ action.sa_handler = sighandler_crash;
443
+ sigemptyset(&action.sa_mask);
444
+ action.sa_flags = 0;
445
+
446
+ SETSIG_IF_UNSET(SIGILL , action);
447
+ SETSIG_IF_UNSET(SIGABRT, action);
448
+ SETSIG_IF_UNSET(SIGFPE , action);
449
+ SETSIG_IF_UNSET(SIGBUS , action);
450
+ SETSIG_IF_UNSET(SIGSEGV, action);
451
+
452
+ symbol_init();
453
+
454
+ atexit(&hash_finalize);
455
+ }
456
+
457
+ /**
458
+ * For general use when testing
459
+ *
460
+ * TODO wrap in #ifdef
461
+ */
462
+
463
+ static bool p_switch = false;
464
+ static bool p_switch_tmp = false;
465
+
466
+ void p(const char *format, ...)
467
+ {
468
+ va_list args;
469
+
470
+ if (!p_switch) return;
471
+
472
+ va_start(args, format);
473
+ vfprintf(stderr, format, args);
474
+ va_end(args);
475
+ }
476
+
477
+ void p_on()
478
+ {
479
+ fprintf(stderr, "> > > > > STARTING PRINT\n");
480
+ p_switch = true;
481
+ }
482
+
483
+ void p_off()
484
+ {
485
+ fprintf(stderr, "< < < < < STOPPING PRINT\n");
486
+ p_switch = false;
487
+ }
488
+
489
+ void p_pause()
490
+ {
491
+ p_switch_tmp = p_switch;
492
+ p_switch = false;
493
+ }
494
+
495
+ void p_resume()
496
+ {
497
+ p_switch = p_switch_tmp;
498
+ }