wapiti 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.autotest +13 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE +30 -0
  6. data/README.md +153 -0
  7. data/Rakefile +33 -0
  8. data/ext/wapiti/bcd.c +392 -0
  9. data/ext/wapiti/decoder.c +535 -0
  10. data/ext/wapiti/decoder.h +46 -0
  11. data/ext/wapiti/extconf.rb +8 -0
  12. data/ext/wapiti/gradient.c +818 -0
  13. data/ext/wapiti/gradient.h +81 -0
  14. data/ext/wapiti/lbfgs.c +294 -0
  15. data/ext/wapiti/model.c +296 -0
  16. data/ext/wapiti/model.h +100 -0
  17. data/ext/wapiti/native.c +1238 -0
  18. data/ext/wapiti/native.h +15 -0
  19. data/ext/wapiti/options.c +278 -0
  20. data/ext/wapiti/options.h +91 -0
  21. data/ext/wapiti/pattern.c +395 -0
  22. data/ext/wapiti/pattern.h +56 -0
  23. data/ext/wapiti/progress.c +167 -0
  24. data/ext/wapiti/progress.h +43 -0
  25. data/ext/wapiti/quark.c +272 -0
  26. data/ext/wapiti/quark.h +46 -0
  27. data/ext/wapiti/reader.c +553 -0
  28. data/ext/wapiti/reader.h +73 -0
  29. data/ext/wapiti/rprop.c +191 -0
  30. data/ext/wapiti/sequence.h +148 -0
  31. data/ext/wapiti/sgdl1.c +218 -0
  32. data/ext/wapiti/thread.c +171 -0
  33. data/ext/wapiti/thread.h +42 -0
  34. data/ext/wapiti/tools.c +202 -0
  35. data/ext/wapiti/tools.h +54 -0
  36. data/ext/wapiti/trainers.h +39 -0
  37. data/ext/wapiti/vmath.c +372 -0
  38. data/ext/wapiti/vmath.h +51 -0
  39. data/ext/wapiti/wapiti.c +288 -0
  40. data/ext/wapiti/wapiti.h +45 -0
  41. data/lib/wapiti.rb +30 -0
  42. data/lib/wapiti/errors.rb +17 -0
  43. data/lib/wapiti/model.rb +49 -0
  44. data/lib/wapiti/options.rb +113 -0
  45. data/lib/wapiti/utility.rb +15 -0
  46. data/lib/wapiti/version.rb +3 -0
  47. data/spec/fixtures/ch.mod +18550 -0
  48. data/spec/fixtures/chpattern.txt +52 -0
  49. data/spec/fixtures/chtest.txt +1973 -0
  50. data/spec/fixtures/chtrain.txt +19995 -0
  51. data/spec/fixtures/nppattern.txt +52 -0
  52. data/spec/fixtures/nptest.txt +1973 -0
  53. data/spec/fixtures/nptrain.txt +19995 -0
  54. data/spec/fixtures/pattern.txt +14 -0
  55. data/spec/fixtures/test.txt +60000 -0
  56. data/spec/fixtures/train.txt +1200 -0
  57. data/spec/spec_helper.rb +21 -0
  58. data/spec/wapiti/model_spec.rb +173 -0
  59. data/spec/wapiti/native_spec.rb +12 -0
  60. data/spec/wapiti/options_spec.rb +175 -0
  61. data/spec/wapiti/utility_spec.rb +22 -0
  62. data/wapiti.gemspec +35 -0
  63. metadata +178 -0
@@ -0,0 +1,171 @@
1
+ /*
2
+ * Wapiti - A linear-chain CRF tool
3
+ *
4
+ * Copyright (c) 2009-2011 CNRS
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include "model.h"
29
+ #include "tools.h"
30
+ #include "thread.h"
31
+ #include "wapiti.h"
32
+
33
+ /******************************************************************************
34
+ * Multi-threading code
35
+ *
36
+ * This module handle the thread managment code using POSIX pthreads, on
37
+ * non-POSIX systems you will have to rewrite this using your systems threads.
38
+ * all code who depend on threads is located here so this process must not be
39
+ * too difficult.
40
+ * If you don't want to use multithreading on non-POSIX system, just enable
41
+ * the definition of MTH_ANSI in wapiti.h. This will disable multithreading.
42
+ *
43
+ * The jobs system is a simple scheduling system, you have to provide the
44
+ * number of jobs to be done and the size of each batch, a call to getjob will
45
+ * return the index of the first available and the size of the batch, and mark
46
+ * these jobs as done. This is usefull if your jobs are numbered but you can't
47
+ * do a trivial split as each of them may require different amount of time to
48
+ * be completed like gradient computation which depend on the length of the
49
+ * sequences.
50
+ * If you provide a count of 0, the job system is disabled.
51
+ ******************************************************************************/
52
+ #ifdef MTH_ANSI
53
+ struct job_s {
54
+ size_t size;
55
+ };
56
+
57
+ bool mth_getjob(job_t *job, size_t *cnt, size_t *pos) {
58
+ if (job->size == 0)
59
+ return false;
60
+ *cnt = job->size;
61
+ *pos = 0;
62
+ job->size = 0;
63
+ return true;
64
+ }
65
+
66
+ void mth_spawn(func_t *f, int W, void *ud[W], size_t size, size_t batch) {
67
+ unused(batch);
68
+ if (size == 0) {
69
+ f(NULL, 0, 1, ud[0]);
70
+ } else {
71
+ job_t job = {size};
72
+ f(&job, 0, 1, ud[0]);
73
+ }
74
+ }
75
+
76
+ #else
77
+
78
+ #include <pthread.h>
79
+
80
+ struct job_s {
81
+ size_t size;
82
+ size_t send;
83
+ size_t batch;
84
+ pthread_mutex_t lock;
85
+ };
86
+
87
+ typedef struct mth_s mth_t;
88
+ struct mth_s {
89
+ job_t *job;
90
+ int id;
91
+ int cnt;
92
+ func_t *f;
93
+ void *ud;
94
+ };
95
+
96
+ /* mth_getjob:
97
+ * Get a new bunch of sequence to process. This function will return a new
98
+ * batch of sequence to process starting at position <pos> and with size
99
+ * <cnt> and return true. If no more batch are available, return false.
100
+ * This function use a lock to ensure thread safety as it will be called by
101
+ * the multiple workers threads.
102
+ */
103
+ bool mth_getjob(job_t *job, size_t *cnt, size_t *pos) {
104
+ if (job == NULL)
105
+ return false;
106
+ if (job->send == job->size)
107
+ return false;
108
+ pthread_mutex_lock(&job->lock);
109
+ *cnt = min(job->batch, job->size - job->send);
110
+ *pos = job->send;
111
+ job->send += *cnt;
112
+ pthread_mutex_unlock(&job->lock);
113
+ return true;
114
+ }
115
+
116
+ static void *mth_stub(void *ud) {
117
+ mth_t *mth = (mth_t *)ud;
118
+ mth->f(mth->job, mth->id, mth->cnt, mth->ud);
119
+ return NULL;
120
+ }
121
+
122
+ /* mth_spawn:
123
+ * This function spawn W threads for calling the 'f' function. The function
124
+ * will get a unique identifier between 0 and W-1 and a user data from the
125
+ * 'ud' array.
126
+ */
127
+ void mth_spawn(func_t *f, int W, void *ud[W], size_t size, size_t batch) {
128
+ // First prepare the jobs scheduler
129
+ job_t job, *pjob = NULL;
130
+ if (size != 0) {
131
+ pjob = &job;
132
+ job.size = size;
133
+ job.send = 0;
134
+ job.batch = batch;
135
+ if (pthread_mutex_init(&job.lock, NULL) != 0)
136
+ fatal("failed to create mutex");
137
+ }
138
+ // We handle differently the case where user requested a single thread
139
+ // for efficiency.
140
+ if (W == 1) {
141
+ f(&job, 0, 1, ud[0]);
142
+ return;
143
+ }
144
+ // We prepare the parameters structures that will be send to the threads
145
+ // with informations for calling the user function.
146
+ mth_t p[W];
147
+ for (int w = 0; w < W; w++) {
148
+ p[w].job = pjob;
149
+ p[w].id = w;
150
+ p[w].cnt = W;
151
+ p[w].f = f;
152
+ p[w].ud = ud[w];
153
+ }
154
+ // We are now ready to spawn the threads and wait for them to finish
155
+ // their jobs. So we just create all the thread and try to join them
156
+ // waiting for there return.
157
+ pthread_attr_t attr;
158
+ pthread_attr_init(&attr);
159
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
160
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
161
+ pthread_t th[W];
162
+ for (int w = 0; w < W; w++)
163
+ if (pthread_create(&th[w], &attr, &mth_stub, &p[w]) != 0)
164
+ fatal("failed to create thread");
165
+ for (int w = 0; w < W; w++)
166
+ if (pthread_join(th[w], NULL) != 0)
167
+ fatal("failed to join thread");
168
+ pthread_attr_destroy(&attr);
169
+ }
170
+ #endif
171
+
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Wapiti - A linear-chain CRF tool
3
+ *
4
+ * Copyright (c) 2009-2011 CNRS
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #ifndef thread_h
29
+ #define thread_h
30
+
31
+ #include <pthread.h>
32
+
33
+ #include "model.h"
34
+
35
+ typedef struct job_s job_t;
36
+
37
+ typedef void (func_t)(job_t *job, int id, int cnt, void *ud);
38
+
39
+ bool mth_getjob(job_t *job, size_t *cnt, size_t *pos);
40
+ void mth_spawn(func_t *f, int W, void *ud[W], size_t size, size_t batch);
41
+
42
+ #endif
@@ -0,0 +1,202 @@
1
+ /*
2
+ * Wapiti - A linear-chain CRF tool
3
+ *
4
+ * Copyright (c) 2009-2011 CNRS
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include <errno.h>
29
+ #include <stdarg.h>
30
+ #include <stddef.h>
31
+ #include <stdlib.h>
32
+ #include <stdio.h>
33
+ #include <string.h>
34
+
35
+ #include "tools.h"
36
+
37
+ /*
38
+ * Wapiti Ruby Logging
39
+ *
40
+ * Wapiti-Ruby delegates all wapiti logging messages to a Ruby logger in the
41
+ * main Wapiti module.
42
+ *
43
+ */
44
+
45
+ #include "native.h"
46
+
47
+
48
+ /*******************************************************************************
49
+ * Error handling and memory managment
50
+ *
51
+ * Wapiti use a very simple system for error handling: violently fail. Errors
52
+ * can occurs in two cases, when user feed Wapiti with bad datas or when there
53
+ * is a problem on the system side. In both cases, there is nothing we can do,
54
+ * so the best thing is to exit with a meaning full error message.
55
+ *
56
+ * Memory allocation is one of the possible point of failure and its painfull
57
+ * to always remeber to check return value of malloc so we provide wrapper
58
+ * around it and realloc who check and fail in case of error.
59
+ ******************************************************************************/
60
+
61
+ /* fatal:
62
+ * This is the main error function, it will print the given message with same
63
+ * formating than the printf family and exit program with an error. We let the
64
+ * OS care about freeing ressources.
65
+ */
66
+ void fatal(const char *msg, ...) {
67
+ va_list args;
68
+ va_start(args, msg);
69
+
70
+ // VALUE message = rb_vsprintf(msg, args);
71
+ VALUE message = rb_str_new2(msg);
72
+
73
+ va_end(args);
74
+
75
+ (void)rb_funcall(cLogger, rb_intern("fatal"), 1, message);
76
+ rb_raise(cNativeError, StringValuePtr(message));
77
+ }
78
+
79
+ /* pfatal:
80
+ * This one is very similar to the fatal function but print an additional
81
+ * system error message depending on the errno. This can be used when a
82
+ * function who set the errno fail to print more detailed informations. You
83
+ * must be carefull to not call other functino that might reset it before
84
+ * calling pfatal.
85
+ */
86
+ void pfatal(const char *msg, ...) {
87
+ const char *err = strerror(errno);
88
+ va_list args;
89
+ va_start(args, msg);
90
+
91
+ // VALUE message = rb_vsprintf(msg, args);
92
+ // rb_str_catf(message, ": <%s>", err);
93
+ VALUE message = rb_str_new2(msg);
94
+
95
+ va_end(args);
96
+
97
+ (void)rb_funcall(cLogger, rb_intern("fatal"), 1, message);
98
+ rb_raise(cNativeError, StringValuePtr(message));
99
+ }
100
+
101
+ /* warning:
102
+ * This one is less violent as it just print a warning on stderr, but doesn't
103
+ * exit the program. It is intended to inform the user that something strange
104
+ * have happen and the result might be not what it have expected.
105
+ */
106
+ void warning(const char *msg, ...) {
107
+ va_list args;
108
+ va_start(args, msg);
109
+
110
+ // (void)rb_funcall(cLogger, rb_intern("warn"), 1, rb_vsprintf(msg, args));
111
+ (void)rb_funcall(cLogger, rb_intern("warn"), 1, rb_str_new2(msg));
112
+
113
+ va_end(args);
114
+ }
115
+
116
+ /* info:
117
+ * Function used for all progress reports. This is where an eventual verbose
118
+ * level can be implemented later or redirection to a logfile. For now, it is
119
+ * just a wrapper for printf to stderr. Note that unlike the previous one,
120
+ * this function doesn't automatically append a new line character.
121
+ */
122
+ void info(const char *msg, ...) {
123
+ va_list args;
124
+ va_start(args, msg);
125
+
126
+ // (void)rb_funcall(cLogger, rb_intern("info"), 1, rb_vsprintf(msg, args));
127
+ (void)rb_funcall(cLogger, rb_intern("info"), 1, rb_str_new2(msg));
128
+
129
+ va_end(args);
130
+ }
131
+
132
+ /* wapiti_xmalloc:
133
+ * A simple wrapper around malloc who violently fail if memory cannot be
134
+ * allocated, so it will never return NULL.
135
+ */
136
+ void *wapiti_xmalloc(size_t size) {
137
+ void *ptr = malloc(size);
138
+ if (ptr == NULL)
139
+ fatal("out of memory");
140
+ return ptr;
141
+ }
142
+
143
+ /* wapiti_xrealloc:
144
+ * As wapiti_xmalloc, this is a simple wrapper around realloc who fail on memory
145
+ * error and so never return NULL.
146
+ */
147
+ void *wapiti_xrealloc(void *ptr, size_t size) {
148
+ void *new = realloc(ptr, size);
149
+ if (new == NULL)
150
+ fatal("out of memory");
151
+ return new;
152
+ }
153
+
154
+ /* xstrdup:
155
+ * As the previous one, this is a safe version of xstrdup who fail on
156
+ * allocation error.
157
+ */
158
+ char *xstrdup(const char *str) {
159
+ const int len = strlen(str) + 1;
160
+ char *res = wapiti_xmalloc(sizeof(char) * len);
161
+ memcpy(res, str, len);
162
+ return res;
163
+ }
164
+
165
+ /******************************************************************************
166
+ * Netstring for persistent storage
167
+ *
168
+ * This follow the format proposed by D.J. Bernstein for safe and portable
169
+ * storage of string in persistent file and networks. This used for storing
170
+ * strings in saved models.
171
+ * We just add an additional end-of-line character to make the output files
172
+ * more readable.
173
+ *
174
+ ******************************************************************************/
175
+
176
+ /* ns_readstr:
177
+ * Read a string from the given file in netstring format. The string is
178
+ * returned as a newly allocated bloc of memory 0-terminated.
179
+ */
180
+ char *ns_readstr(FILE *file) {
181
+ int len;
182
+ if (fscanf(file, "%d:", &len) != 1)
183
+ pfatal("cannot read from file");
184
+ char *buf = wapiti_xmalloc(len + 1);
185
+ if (fread(buf, len, 1, file) != 1)
186
+ pfatal("cannot read from file");
187
+ if (fgetc(file) != ',')
188
+ fatal("invalid format");
189
+ buf[len] = '\0';
190
+ fgetc(file);
191
+ return buf;
192
+ }
193
+
194
+ /* ns_writestr:
195
+ * Write a string in the netstring format to the given file.
196
+ */
197
+ void ns_writestr(FILE *file, const char *str) {
198
+ const int len = strlen(str);
199
+ if (fprintf(file, "%d:%s,\n", len, str) < 0)
200
+ pfatal("cannot write to file");
201
+ }
202
+
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Wapiti - A linear-chain CRF tool
3
+ *
4
+ * Copyright (c) 2009-2011 CNRS
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ *
15
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ * POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+ #ifndef tools_h
28
+ #define tools_h
29
+
30
+ #include <stdarg.h>
31
+ #include <stddef.h>
32
+ #include <stdio.h>
33
+
34
+ #include <ruby.h>
35
+
36
+ #define unused(v) ((void)(v))
37
+ #define none ((size_t)-1)
38
+
39
+ #define min(a, b) ((a) < (b) ? (a) : (b))
40
+ #define max(a, b) ((a) < (b) ? (b) : (a))
41
+
42
+ void fatal(const char *msg, ...);
43
+ void pfatal(const char *msg, ...);
44
+ void warning(const char *msg, ...);
45
+ void info(const char *msg, ...);
46
+
47
+ void *wapiti_xmalloc(size_t size);
48
+ void *wapiti_xrealloc(void *ptr, size_t size);
49
+ char *xstrdup(const char *str);
50
+
51
+ char *ns_readstr(FILE *file);
52
+ void ns_writestr(FILE *file, const char *str);
53
+
54
+ #endif