cadical 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +26 -0
- data/README.md +101 -0
- data/ext/cadical/cadical/LICENSE +28 -0
- data/ext/cadical/cadical/README.md +65 -0
- data/ext/cadical/cadical/VERSION +1 -0
- data/ext/cadical/cadical/src/analyze.cpp +1360 -0
- data/ext/cadical/cadical/src/arena.cpp +30 -0
- data/ext/cadical/cadical/src/arena.hpp +105 -0
- data/ext/cadical/cadical/src/assume.cpp +616 -0
- data/ext/cadical/cadical/src/averages.cpp +34 -0
- data/ext/cadical/cadical/src/averages.hpp +37 -0
- data/ext/cadical/cadical/src/backbone.cpp +631 -0
- data/ext/cadical/cadical/src/backtrack.cpp +177 -0
- data/ext/cadical/cadical/src/backward.cpp +231 -0
- data/ext/cadical/cadical/src/bins.cpp +22 -0
- data/ext/cadical/cadical/src/bins.hpp +22 -0
- data/ext/cadical/cadical/src/block.cpp +824 -0
- data/ext/cadical/cadical/src/block.hpp +37 -0
- data/ext/cadical/cadical/src/cadical.cpp +1026 -0
- data/ext/cadical/cadical/src/cadical.hpp +1419 -0
- data/ext/cadical/cadical/src/ccadical.cpp +208 -0
- data/ext/cadical/cadical/src/ccadical.h +74 -0
- data/ext/cadical/cadical/src/checker.cpp +649 -0
- data/ext/cadical/cadical/src/checker.hpp +173 -0
- data/ext/cadical/cadical/src/clause.cpp +689 -0
- data/ext/cadical/cadical/src/clause.hpp +190 -0
- data/ext/cadical/cadical/src/collect.cpp +545 -0
- data/ext/cadical/cadical/src/compact.cpp +550 -0
- data/ext/cadical/cadical/src/condition.cpp +940 -0
- data/ext/cadical/cadical/src/config.cpp +101 -0
- data/ext/cadical/cadical/src/config.hpp +20 -0
- data/ext/cadical/cadical/src/congruence.cpp +7880 -0
- data/ext/cadical/cadical/src/congruence.hpp +757 -0
- data/ext/cadical/cadical/src/constrain.cpp +64 -0
- data/ext/cadical/cadical/src/contract.cpp +27 -0
- data/ext/cadical/cadical/src/contract.hpp +139 -0
- data/ext/cadical/cadical/src/cover.cpp +704 -0
- data/ext/cadical/cadical/src/cover.hpp +34 -0
- data/ext/cadical/cadical/src/decide.cpp +347 -0
- data/ext/cadical/cadical/src/decompose.cpp +738 -0
- data/ext/cadical/cadical/src/decompose.hpp +23 -0
- data/ext/cadical/cadical/src/deduplicate.cpp +275 -0
- data/ext/cadical/cadical/src/definition.cpp +283 -0
- data/ext/cadical/cadical/src/delay.hpp +38 -0
- data/ext/cadical/cadical/src/drattracer.cpp +153 -0
- data/ext/cadical/cadical/src/drattracer.hpp +55 -0
- data/ext/cadical/cadical/src/elim.cpp +1171 -0
- data/ext/cadical/cadical/src/elim.hpp +53 -0
- data/ext/cadical/cadical/src/elimfast.cpp +570 -0
- data/ext/cadical/cadical/src/ema.cpp +95 -0
- data/ext/cadical/cadical/src/ema.hpp +68 -0
- data/ext/cadical/cadical/src/extend.cpp +289 -0
- data/ext/cadical/cadical/src/external.cpp +1034 -0
- data/ext/cadical/cadical/src/external.hpp +487 -0
- data/ext/cadical/cadical/src/external_propagate.cpp +1316 -0
- data/ext/cadical/cadical/src/factor.cpp +1011 -0
- data/ext/cadical/cadical/src/factor.hpp +54 -0
- data/ext/cadical/cadical/src/file.cpp +506 -0
- data/ext/cadical/cadical/src/file.hpp +210 -0
- data/ext/cadical/cadical/src/flags.cpp +135 -0
- data/ext/cadical/cadical/src/flags.hpp +93 -0
- data/ext/cadical/cadical/src/flip.cpp +269 -0
- data/ext/cadical/cadical/src/format.cpp +89 -0
- data/ext/cadical/cadical/src/format.hpp +36 -0
- data/ext/cadical/cadical/src/frattracer.cpp +277 -0
- data/ext/cadical/cadical/src/frattracer.hpp +67 -0
- data/ext/cadical/cadical/src/gates.cpp +766 -0
- data/ext/cadical/cadical/src/heap.hpp +212 -0
- data/ext/cadical/cadical/src/idruptracer.cpp +566 -0
- data/ext/cadical/cadical/src/idruptracer.hpp +112 -0
- data/ext/cadical/cadical/src/instantiate.cpp +365 -0
- data/ext/cadical/cadical/src/instantiate.hpp +45 -0
- data/ext/cadical/cadical/src/internal.cpp +1265 -0
- data/ext/cadical/cadical/src/internal.hpp +1941 -0
- data/ext/cadical/cadical/src/inttypes.hpp +34 -0
- data/ext/cadical/cadical/src/ipasir.cpp +47 -0
- data/ext/cadical/cadical/src/ipasir.h +37 -0
- data/ext/cadical/cadical/src/kitten.c +2599 -0
- data/ext/cadical/cadical/src/kitten.h +97 -0
- data/ext/cadical/cadical/src/level.hpp +33 -0
- data/ext/cadical/cadical/src/lidruptracer.cpp +657 -0
- data/ext/cadical/cadical/src/lidruptracer.hpp +122 -0
- data/ext/cadical/cadical/src/limit.cpp +146 -0
- data/ext/cadical/cadical/src/limit.hpp +168 -0
- data/ext/cadical/cadical/src/logging.cpp +214 -0
- data/ext/cadical/cadical/src/logging.hpp +98 -0
- data/ext/cadical/cadical/src/lookahead.cpp +520 -0
- data/ext/cadical/cadical/src/lratchecker.cpp +833 -0
- data/ext/cadical/cadical/src/lratchecker.hpp +168 -0
- data/ext/cadical/cadical/src/lrattracer.cpp +200 -0
- data/ext/cadical/cadical/src/lrattracer.hpp +61 -0
- data/ext/cadical/cadical/src/lucky.cpp +506 -0
- data/ext/cadical/cadical/src/message.cpp +218 -0
- data/ext/cadical/cadical/src/message.hpp +65 -0
- data/ext/cadical/cadical/src/minimize.cpp +224 -0
- data/ext/cadical/cadical/src/mobical.cpp +5588 -0
- data/ext/cadical/cadical/src/occs.cpp +52 -0
- data/ext/cadical/cadical/src/occs.hpp +36 -0
- data/ext/cadical/cadical/src/options.cpp +359 -0
- data/ext/cadical/cadical/src/options.hpp +442 -0
- data/ext/cadical/cadical/src/parse.cpp +471 -0
- data/ext/cadical/cadical/src/parse.hpp +75 -0
- data/ext/cadical/cadical/src/phases.cpp +56 -0
- data/ext/cadical/cadical/src/phases.hpp +19 -0
- data/ext/cadical/cadical/src/probe.cpp +990 -0
- data/ext/cadical/cadical/src/profile.cpp +107 -0
- data/ext/cadical/cadical/src/profile.hpp +283 -0
- data/ext/cadical/cadical/src/proof.cpp +691 -0
- data/ext/cadical/cadical/src/proof.hpp +125 -0
- data/ext/cadical/cadical/src/propagate.cpp +584 -0
- data/ext/cadical/cadical/src/queue.cpp +90 -0
- data/ext/cadical/cadical/src/queue.hpp +74 -0
- data/ext/cadical/cadical/src/radix.hpp +180 -0
- data/ext/cadical/cadical/src/random.cpp +207 -0
- data/ext/cadical/cadical/src/random.h +44 -0
- data/ext/cadical/cadical/src/random.hpp +98 -0
- data/ext/cadical/cadical/src/range.hpp +125 -0
- data/ext/cadical/cadical/src/reap.cpp +127 -0
- data/ext/cadical/cadical/src/reap.hpp +28 -0
- data/ext/cadical/cadical/src/reduce.cpp +278 -0
- data/ext/cadical/cadical/src/reluctant.hpp +82 -0
- data/ext/cadical/cadical/src/rephase.cpp +402 -0
- data/ext/cadical/cadical/src/report.cpp +313 -0
- data/ext/cadical/cadical/src/resources.cpp +160 -0
- data/ext/cadical/cadical/src/resources.hpp +16 -0
- data/ext/cadical/cadical/src/restart.cpp +178 -0
- data/ext/cadical/cadical/src/restore.cpp +267 -0
- data/ext/cadical/cadical/src/score.cpp +51 -0
- data/ext/cadical/cadical/src/score.hpp +16 -0
- data/ext/cadical/cadical/src/shrink.cpp +507 -0
- data/ext/cadical/cadical/src/signal.cpp +136 -0
- data/ext/cadical/cadical/src/signal.hpp +33 -0
- data/ext/cadical/cadical/src/solution.cpp +50 -0
- data/ext/cadical/cadical/src/solver.cpp +1871 -0
- data/ext/cadical/cadical/src/stable.cpp +31 -0
- data/ext/cadical/cadical/src/stack.h +110 -0
- data/ext/cadical/cadical/src/stats.cpp +920 -0
- data/ext/cadical/cadical/src/stats.hpp +418 -0
- data/ext/cadical/cadical/src/subsume.cpp +645 -0
- data/ext/cadical/cadical/src/sweep.cpp +1960 -0
- data/ext/cadical/cadical/src/sweep.hpp +61 -0
- data/ext/cadical/cadical/src/terminal.cpp +38 -0
- data/ext/cadical/cadical/src/terminal.hpp +96 -0
- data/ext/cadical/cadical/src/ternary.cpp +450 -0
- data/ext/cadical/cadical/src/testing.hpp +24 -0
- data/ext/cadical/cadical/src/tier.cpp +189 -0
- data/ext/cadical/cadical/src/tracer.hpp +186 -0
- data/ext/cadical/cadical/src/transred.cpp +253 -0
- data/ext/cadical/cadical/src/unstable.cpp +29 -0
- data/ext/cadical/cadical/src/util.cpp +129 -0
- data/ext/cadical/cadical/src/util.hpp +181 -0
- data/ext/cadical/cadical/src/var.cpp +39 -0
- data/ext/cadical/cadical/src/var.hpp +22 -0
- data/ext/cadical/cadical/src/veripbtracer.cpp +427 -0
- data/ext/cadical/cadical/src/veripbtracer.hpp +106 -0
- data/ext/cadical/cadical/src/version.cpp +107 -0
- data/ext/cadical/cadical/src/version.hpp +13 -0
- data/ext/cadical/cadical/src/vivify.cpp +1893 -0
- data/ext/cadical/cadical/src/vivify.hpp +50 -0
- data/ext/cadical/cadical/src/walk.cpp +1088 -0
- data/ext/cadical/cadical/src/walk.hpp +91 -0
- data/ext/cadical/cadical/src/walk_full_occs.cpp +966 -0
- data/ext/cadical/cadical/src/warmup.cpp +403 -0
- data/ext/cadical/cadical/src/watch.cpp +126 -0
- data/ext/cadical/cadical/src/watch.hpp +77 -0
- data/ext/cadical/cadical_ext.c +778 -0
- data/ext/cadical/extconf.rb +26 -0
- data/lib/cadical/version.rb +3 -0
- data/lib/cadical.rb +12 -0
- metadata +218 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#ifndef _factor_hpp_INCLUDED
|
|
2
|
+
#define _factor_hpp_INCLUDED
|
|
3
|
+
|
|
4
|
+
#include "clause.hpp"
|
|
5
|
+
#include "heap.hpp"
|
|
6
|
+
|
|
7
|
+
namespace CaDiCaL {
|
|
8
|
+
|
|
9
|
+
struct Internal;
|
|
10
|
+
|
|
11
|
+
struct factor_occs_size {
|
|
12
|
+
Internal *internal;
|
|
13
|
+
factor_occs_size (Internal *i) : internal (i) {}
|
|
14
|
+
bool operator() (unsigned a, unsigned b);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
struct Quotient {
|
|
18
|
+
Quotient (int f) : factor (f) {}
|
|
19
|
+
~Quotient () {}
|
|
20
|
+
int factor;
|
|
21
|
+
size_t id;
|
|
22
|
+
int64_t bid; // for LRAT
|
|
23
|
+
Quotient *prev, *next;
|
|
24
|
+
vector<Clause *> qlauses;
|
|
25
|
+
vector<size_t> matches;
|
|
26
|
+
size_t matched;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
typedef heap<factor_occs_size> FactorSchedule;
|
|
30
|
+
|
|
31
|
+
struct Factoring {
|
|
32
|
+
Factoring (Internal *, int64_t);
|
|
33
|
+
~Factoring ();
|
|
34
|
+
|
|
35
|
+
// These are initialized by the constructor
|
|
36
|
+
Internal *internal;
|
|
37
|
+
int64_t limit;
|
|
38
|
+
FactorSchedule schedule;
|
|
39
|
+
|
|
40
|
+
int initial;
|
|
41
|
+
int bound;
|
|
42
|
+
vector<unsigned> count;
|
|
43
|
+
vector<int> fresh;
|
|
44
|
+
vector<int> counted;
|
|
45
|
+
vector<int> nounted;
|
|
46
|
+
vector<Clause *> flauses;
|
|
47
|
+
struct {
|
|
48
|
+
Quotient *first, *last;
|
|
49
|
+
} quotients;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
} // namespace CaDiCaL
|
|
53
|
+
|
|
54
|
+
#endif
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
#include "internal.hpp"
|
|
2
|
+
|
|
3
|
+
/*------------------------------------------------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Some more low-level 'C' headers.
|
|
6
|
+
|
|
7
|
+
extern "C" {
|
|
8
|
+
#include <errno.h>
|
|
9
|
+
#include <fcntl.h>
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
#include <sys/stat.h>
|
|
13
|
+
#include <sys/types.h>
|
|
14
|
+
#include <unistd.h>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#ifndef _WIN32
|
|
18
|
+
|
|
19
|
+
extern "C" {
|
|
20
|
+
#include <sys/wait.h>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
#if defined(__APPLE__) || defined(__MACH__)
|
|
26
|
+
|
|
27
|
+
extern "C" {
|
|
28
|
+
#include <libproc.h>
|
|
29
|
+
#include <sys/proc_info.h>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#include <mutex>
|
|
33
|
+
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
/*------------------------------------------------------------------------*/
|
|
37
|
+
|
|
38
|
+
namespace CaDiCaL {
|
|
39
|
+
|
|
40
|
+
/*------------------------------------------------------------------------*/
|
|
41
|
+
|
|
42
|
+
// Private constructor.
|
|
43
|
+
|
|
44
|
+
File::File (Internal *i, bool w, int c, int p, FILE *f, const char *n)
|
|
45
|
+
: internal (i),
|
|
46
|
+
#if !defined(QUIET) || !defined(NDEBUG)
|
|
47
|
+
writing (w),
|
|
48
|
+
#endif
|
|
49
|
+
close_file (c), child_pid (p), file (f), _name (strdup (n)),
|
|
50
|
+
_lineno (1), _bytes (0) {
|
|
51
|
+
(void) w;
|
|
52
|
+
assert (f), assert (n);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/*------------------------------------------------------------------------*/
|
|
56
|
+
|
|
57
|
+
bool File::exists (const char *path) {
|
|
58
|
+
struct stat buf;
|
|
59
|
+
if (stat (path, &buf))
|
|
60
|
+
return false;
|
|
61
|
+
if (access (path, R_OK))
|
|
62
|
+
return false;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
bool File::writable (const char *path) {
|
|
67
|
+
int res;
|
|
68
|
+
if (!path)
|
|
69
|
+
res = 1;
|
|
70
|
+
else if (!strcmp (path, "/dev/null"))
|
|
71
|
+
res = 0;
|
|
72
|
+
else {
|
|
73
|
+
if (!*path)
|
|
74
|
+
res = 2;
|
|
75
|
+
else {
|
|
76
|
+
struct stat buf;
|
|
77
|
+
const char *p = strrchr (path, '/');
|
|
78
|
+
if (!p) {
|
|
79
|
+
if (stat (path, &buf))
|
|
80
|
+
res = ((errno == ENOENT) ? 0 : -2);
|
|
81
|
+
else if (S_ISDIR (buf.st_mode))
|
|
82
|
+
res = 3;
|
|
83
|
+
else
|
|
84
|
+
res = (access (path, W_OK) ? 4 : 0);
|
|
85
|
+
} else if (!p[1])
|
|
86
|
+
res = 5;
|
|
87
|
+
else {
|
|
88
|
+
size_t len = p - path;
|
|
89
|
+
char *dirname = new char[len + 1];
|
|
90
|
+
strncpy (dirname, path, len);
|
|
91
|
+
dirname[len] = 0;
|
|
92
|
+
if (stat (dirname, &buf))
|
|
93
|
+
res = 6;
|
|
94
|
+
else if (!S_ISDIR (buf.st_mode))
|
|
95
|
+
res = 7;
|
|
96
|
+
else if (access (dirname, W_OK))
|
|
97
|
+
res = 8;
|
|
98
|
+
else if (stat (path, &buf))
|
|
99
|
+
res = (errno == ENOENT) ? 0 : -3;
|
|
100
|
+
else
|
|
101
|
+
res = access (path, W_OK) ? 9 : 0;
|
|
102
|
+
delete[] dirname;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return !res;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
bool File::piping () {
|
|
110
|
+
struct stat stat;
|
|
111
|
+
int fd = fileno (file);
|
|
112
|
+
if (fstat (fd, &stat))
|
|
113
|
+
return true;
|
|
114
|
+
return S_ISFIFO (stat.st_mode);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// These are signatures for supported compressed file types. In 2018 the
|
|
118
|
+
// SAT Competition was running on StarExec and used internally 'bzip2'
|
|
119
|
+
// compressed files, but gave them uncompressed to the solver using exactly
|
|
120
|
+
// the same path (with '.bz2' suffix). Then 'CaDiCaL' tried to read that
|
|
121
|
+
// actually uncompressed file through 'bzip2', which of course failed. Now
|
|
122
|
+
// we double check and fall back to reading the file as is, if the signature
|
|
123
|
+
// does not match after issuing a warning.
|
|
124
|
+
|
|
125
|
+
static int xzsig[] = {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00, 0x00, EOF};
|
|
126
|
+
static int bz2sig[] = {0x42, 0x5A, 0x68, EOF};
|
|
127
|
+
static int gzsig[] = {0x1F, 0x8B, EOF};
|
|
128
|
+
static int sig7z[] = {0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C, EOF};
|
|
129
|
+
static int lzmasig[] = {0x5D, EOF};
|
|
130
|
+
|
|
131
|
+
bool File::match (Internal *internal, const char *path, const int *sig) {
|
|
132
|
+
assert (path);
|
|
133
|
+
FILE *tmp = fopen (path, "r");
|
|
134
|
+
if (!tmp) {
|
|
135
|
+
WARNING ("failed to open '%s' to check signature", path);
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
bool res = true;
|
|
139
|
+
for (const int *p = sig; res && (*p != EOF); p++)
|
|
140
|
+
res = (cadical_getc_unlocked (tmp) == *p);
|
|
141
|
+
fclose (tmp);
|
|
142
|
+
if (!res)
|
|
143
|
+
WARNING ("file type signature check for '%s' failed", path);
|
|
144
|
+
return res;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
size_t File::size (const char *path) {
|
|
148
|
+
struct stat buf;
|
|
149
|
+
if (stat (path, &buf))
|
|
150
|
+
return 0;
|
|
151
|
+
return (size_t) buf.st_size;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Check that 'prg' is in the 'PATH' and thus can be found if executed
|
|
155
|
+
// through 'popen' or 'exec'.
|
|
156
|
+
|
|
157
|
+
char *File::find_program (const char *prg) {
|
|
158
|
+
size_t prglen = strlen (prg);
|
|
159
|
+
const char *c = getenv ("PATH");
|
|
160
|
+
if (!c)
|
|
161
|
+
return 0;
|
|
162
|
+
size_t len = strlen (c);
|
|
163
|
+
char *e = new char[len + 1];
|
|
164
|
+
strcpy (e, c);
|
|
165
|
+
char *res = 0;
|
|
166
|
+
for (char *p = e, *q; !res && p < e + len; p = q) {
|
|
167
|
+
for (q = p; *q && *q != ':'; q++)
|
|
168
|
+
;
|
|
169
|
+
*q++ = 0;
|
|
170
|
+
size_t pathlen = (q - p) + prglen;
|
|
171
|
+
char *path = new char[pathlen + 1];
|
|
172
|
+
snprintf (path, pathlen + 1, "%s/%s", p, prg);
|
|
173
|
+
assert (strlen (path) == pathlen);
|
|
174
|
+
if (exists (path))
|
|
175
|
+
res = path;
|
|
176
|
+
else
|
|
177
|
+
delete[] path;
|
|
178
|
+
}
|
|
179
|
+
delete[] e;
|
|
180
|
+
return res;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/*------------------------------------------------------------------------*/
|
|
184
|
+
|
|
185
|
+
FILE *File::open_file (Internal *internal, const char *path,
|
|
186
|
+
const char *mode) {
|
|
187
|
+
(void) internal;
|
|
188
|
+
return fopen (path, mode);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
FILE *File::read_file (Internal *internal, const char *path) {
|
|
192
|
+
MSG ("opening file to read '%s'", path);
|
|
193
|
+
return open_file (internal, path, "r");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
FILE *File::write_file (Internal *internal, const char *path) {
|
|
197
|
+
MSG ("opening file to write '%s'", path);
|
|
198
|
+
return open_file (internal, path, "wb");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/*------------------------------------------------------------------------*/
|
|
202
|
+
|
|
203
|
+
void File::split_str (const char *command, std::vector<char *> &argv) {
|
|
204
|
+
const char *c = command;
|
|
205
|
+
while (*c && *c == ' ')
|
|
206
|
+
c++;
|
|
207
|
+
while (*c) {
|
|
208
|
+
const char *p = c;
|
|
209
|
+
while (*p && *p != ' ')
|
|
210
|
+
p++;
|
|
211
|
+
const size_t bytes = p - c;
|
|
212
|
+
char *arg = new char[bytes + 1];
|
|
213
|
+
(void) strncpy (arg, c, bytes);
|
|
214
|
+
arg[bytes] = 0;
|
|
215
|
+
argv.push_back (arg);
|
|
216
|
+
while (*p && *p == ' ')
|
|
217
|
+
p++;
|
|
218
|
+
c = p;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
void File::delete_str_vector (std::vector<char *> &argv) {
|
|
223
|
+
for (auto str : argv)
|
|
224
|
+
delete[] str;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
FILE *File::open_pipe (Internal *internal, const char *fmt,
|
|
228
|
+
const char *path, const char *mode) {
|
|
229
|
+
#ifdef QUIET
|
|
230
|
+
(void) internal;
|
|
231
|
+
#endif
|
|
232
|
+
size_t prglen = 0;
|
|
233
|
+
while (fmt[prglen] && fmt[prglen] != ' ')
|
|
234
|
+
prglen++;
|
|
235
|
+
char *prg = new char[prglen + 1];
|
|
236
|
+
strncpy (prg, fmt, prglen);
|
|
237
|
+
prg[prglen] = 0;
|
|
238
|
+
char *found = find_program (prg);
|
|
239
|
+
if (found)
|
|
240
|
+
MSG ("found '%s' in path for '%s'", found, prg);
|
|
241
|
+
if (!found)
|
|
242
|
+
MSG ("did not find '%s' in path", prg);
|
|
243
|
+
delete[] prg;
|
|
244
|
+
if (!found)
|
|
245
|
+
return 0;
|
|
246
|
+
delete[] found;
|
|
247
|
+
size_t cmd_size = strlen (fmt) + strlen (path);
|
|
248
|
+
char *cmd = new char[cmd_size];
|
|
249
|
+
snprintf (cmd, cmd_size, fmt, path);
|
|
250
|
+
FILE *res = popen (cmd, mode);
|
|
251
|
+
delete[] cmd;
|
|
252
|
+
return res;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
FILE *File::read_pipe (Internal *internal, const char *fmt, const int *sig,
|
|
256
|
+
const char *path) {
|
|
257
|
+
if (!File::exists (path)) {
|
|
258
|
+
LOG ("file '%s' does not exist", path);
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
LOG ("file '%s' exists", path);
|
|
262
|
+
if (sig && !File::match (internal, path, sig))
|
|
263
|
+
return 0;
|
|
264
|
+
LOG ("file '%s' matches signature for '%s'", path, fmt);
|
|
265
|
+
MSG ("opening pipe to read '%s'", path);
|
|
266
|
+
return open_pipe (internal, fmt, path, "r");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
#ifndef _WIN32
|
|
270
|
+
|
|
271
|
+
#if defined(__APPLE__) || defined(__MACH__)
|
|
272
|
+
static std::mutex compressed_file_writing_mutex;
|
|
273
|
+
#endif
|
|
274
|
+
|
|
275
|
+
FILE *File::write_pipe (Internal *internal, const char *command,
|
|
276
|
+
const char *path, int &child_pid) {
|
|
277
|
+
assert (command[0] && command[0] != ' ');
|
|
278
|
+
MSG ("writing through command '%s' to '%s'", command, path);
|
|
279
|
+
#ifdef QUIET
|
|
280
|
+
(void) internal;
|
|
281
|
+
#endif
|
|
282
|
+
std::vector<char *> args;
|
|
283
|
+
split_str (command, args);
|
|
284
|
+
assert (!args.empty ());
|
|
285
|
+
args.push_back (0);
|
|
286
|
+
char **argv = args.data ();
|
|
287
|
+
char *absolute_command_path = find_program (argv[0]);
|
|
288
|
+
int pipe_fds[2], out;
|
|
289
|
+
FILE *res = 0;
|
|
290
|
+
#if defined(__APPLE__) || defined(__MACH__)
|
|
291
|
+
compressed_file_writing_mutex.lock ();
|
|
292
|
+
#endif
|
|
293
|
+
if (!absolute_command_path)
|
|
294
|
+
MSG ("could not find '%s' in 'PATH' environment variable", argv[0]);
|
|
295
|
+
else if (::pipe (pipe_fds) < 0)
|
|
296
|
+
MSG ("could not generate pipe to '%s' command", command);
|
|
297
|
+
else if ((out = ::open (path, O_CREAT | O_TRUNC | O_WRONLY, 0644)) < 0)
|
|
298
|
+
MSG ("could not open '%s' for writing", path);
|
|
299
|
+
else if ((child_pid = ::fork ()) < 0) {
|
|
300
|
+
MSG ("could not fork process to execute '%s' command", command);
|
|
301
|
+
::close (out);
|
|
302
|
+
} else if (child_pid) {
|
|
303
|
+
::close (pipe_fds[0]);
|
|
304
|
+
res = ::fdopen (pipe_fds[1], "wb");
|
|
305
|
+
} else {
|
|
306
|
+
|
|
307
|
+
// Connect stdin and stdout in child
|
|
308
|
+
|
|
309
|
+
::dup2 (pipe_fds[0], 0);
|
|
310
|
+
::dup2 (out, 1);
|
|
311
|
+
|
|
312
|
+
// Make sure to close all non-required fds to not cause hangs.
|
|
313
|
+
// This is handled now by closefrom and remains for documentation
|
|
314
|
+
// purposes:
|
|
315
|
+
//
|
|
316
|
+
// ::close (pipe_fds[0]);
|
|
317
|
+
// ::close (pipe_fds[1]);
|
|
318
|
+
// ::close (out);
|
|
319
|
+
|
|
320
|
+
// Surpress '7z' verbose output on 'stderr'.
|
|
321
|
+
|
|
322
|
+
if (command[0] == '7') {
|
|
323
|
+
::close (2);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Before the fork another thread could have created more fds. These
|
|
327
|
+
// fds are cloned into the child process. As this inhibits pipes to
|
|
328
|
+
// be closed by the parent process we have to close all of the
|
|
329
|
+
// erroneously cloned fds here.
|
|
330
|
+
|
|
331
|
+
#ifndef NCLOSEFROM
|
|
332
|
+
::closefrom (3);
|
|
333
|
+
#else
|
|
334
|
+
// Simplistic replacement on Unix without 'closefrom'.
|
|
335
|
+
for (int fd = 3; fd != FD_SETSIZE; fd++)
|
|
336
|
+
::close (fd);
|
|
337
|
+
#endif
|
|
338
|
+
execv (absolute_command_path, argv);
|
|
339
|
+
_exit (1);
|
|
340
|
+
}
|
|
341
|
+
if (absolute_command_path)
|
|
342
|
+
delete[] absolute_command_path;
|
|
343
|
+
delete_str_vector (args);
|
|
344
|
+
#ifdef QUIET
|
|
345
|
+
(void) internal;
|
|
346
|
+
#endif
|
|
347
|
+
#if defined(__APPLE__) || defined(__MACH__)
|
|
348
|
+
if (!res)
|
|
349
|
+
compressed_file_writing_mutex.unlock ();
|
|
350
|
+
#endif
|
|
351
|
+
return res;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
#endif
|
|
355
|
+
|
|
356
|
+
/*------------------------------------------------------------------------*/
|
|
357
|
+
|
|
358
|
+
File *File::read (Internal *internal, FILE *f, const char *n) {
|
|
359
|
+
return new File (internal, false, 0, 0, f, n);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
File *File::write (Internal *internal, FILE *f, const char *n) {
|
|
363
|
+
return new File (internal, true, 0, 0, f, n);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
File *File::read (Internal *internal, const char *path) {
|
|
367
|
+
FILE *file;
|
|
368
|
+
int close_input = 2;
|
|
369
|
+
if (has_suffix (path, ".xz")) {
|
|
370
|
+
file = read_pipe (internal, "xz -c -d %s", xzsig, path);
|
|
371
|
+
if (!file)
|
|
372
|
+
goto READ_FILE;
|
|
373
|
+
} else if (has_suffix (path, ".lzma")) {
|
|
374
|
+
file = read_pipe (internal, "lzma -c -d %s", lzmasig, path);
|
|
375
|
+
if (!file)
|
|
376
|
+
goto READ_FILE;
|
|
377
|
+
} else if (has_suffix (path, ".bz2")) {
|
|
378
|
+
file = read_pipe (internal, "bzip2 -c -d %s", bz2sig, path);
|
|
379
|
+
if (!file)
|
|
380
|
+
goto READ_FILE;
|
|
381
|
+
} else if (has_suffix (path, ".gz")) {
|
|
382
|
+
file = read_pipe (internal, "gzip -c -d %s", gzsig, path);
|
|
383
|
+
if (!file)
|
|
384
|
+
goto READ_FILE;
|
|
385
|
+
} else if (has_suffix (path, ".7z")) {
|
|
386
|
+
file = read_pipe (internal, "7z x -so %s 2>/dev/null", sig7z, path);
|
|
387
|
+
if (!file)
|
|
388
|
+
goto READ_FILE;
|
|
389
|
+
} else {
|
|
390
|
+
READ_FILE:
|
|
391
|
+
file = read_file (internal, path);
|
|
392
|
+
close_input = 1;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (!file)
|
|
396
|
+
return 0;
|
|
397
|
+
|
|
398
|
+
return new File (internal, false, close_input, 0, file, path);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
File *File::write (Internal *internal, const char *path) {
|
|
402
|
+
FILE *file;
|
|
403
|
+
int close_output = 3, child_pid = 0;
|
|
404
|
+
#ifndef _WIN32
|
|
405
|
+
if (has_suffix (path, ".xz"))
|
|
406
|
+
file = write_pipe (internal, "xz -c", path, child_pid);
|
|
407
|
+
else if (has_suffix (path, ".bz2"))
|
|
408
|
+
file = write_pipe (internal, "bzip2 -c", path, child_pid);
|
|
409
|
+
else if (has_suffix (path, ".gz"))
|
|
410
|
+
file = write_pipe (internal, "gzip -c", path, child_pid);
|
|
411
|
+
else if (has_suffix (path, ".7z"))
|
|
412
|
+
file = write_pipe (internal, "7z a -an -txz -si -so", path, child_pid);
|
|
413
|
+
else
|
|
414
|
+
#endif
|
|
415
|
+
file = write_file (internal, path), close_output = 1;
|
|
416
|
+
|
|
417
|
+
if (!file)
|
|
418
|
+
return 0;
|
|
419
|
+
|
|
420
|
+
return new File (internal, true, close_output, child_pid, file, path);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
void File::close (bool print) {
|
|
424
|
+
assert (file);
|
|
425
|
+
#ifndef QUIET
|
|
426
|
+
if (internal->opts.quiet)
|
|
427
|
+
print = false;
|
|
428
|
+
else if (internal->opts.verbose > 0)
|
|
429
|
+
print = true;
|
|
430
|
+
#endif
|
|
431
|
+
if (close_file == 0) {
|
|
432
|
+
if (print)
|
|
433
|
+
MSG ("disconnecting from '%s'", name ());
|
|
434
|
+
}
|
|
435
|
+
if (close_file == 1) {
|
|
436
|
+
if (print)
|
|
437
|
+
MSG ("closing file '%s'", name ());
|
|
438
|
+
fclose (file);
|
|
439
|
+
}
|
|
440
|
+
if (close_file == 2) {
|
|
441
|
+
if (print)
|
|
442
|
+
MSG ("closing input pipe to read '%s'", name ());
|
|
443
|
+
pclose (file);
|
|
444
|
+
}
|
|
445
|
+
#ifndef _WIN32
|
|
446
|
+
if (close_file == 3) {
|
|
447
|
+
if (print)
|
|
448
|
+
MSG ("closing output pipe to write '%s'", name ());
|
|
449
|
+
fclose (file);
|
|
450
|
+
waitpid (child_pid, 0, 0);
|
|
451
|
+
#if defined(__APPLE__) || defined(__MACH__)
|
|
452
|
+
compressed_file_writing_mutex.unlock ();
|
|
453
|
+
#endif
|
|
454
|
+
}
|
|
455
|
+
#endif
|
|
456
|
+
file = 0; // mark as closed
|
|
457
|
+
|
|
458
|
+
// TODO what about error checking for 'fclose', 'pclose' or 'waitpid'?
|
|
459
|
+
|
|
460
|
+
#ifndef QUIET
|
|
461
|
+
if (print) {
|
|
462
|
+
if (writing) {
|
|
463
|
+
uint64_t written_bytes = bytes ();
|
|
464
|
+
double written_mb = written_bytes / (double) (1 << 20);
|
|
465
|
+
MSG ("after writing %" PRIu64 " bytes %.1f MB", written_bytes,
|
|
466
|
+
written_mb);
|
|
467
|
+
if (close_file == 3) {
|
|
468
|
+
size_t actual_bytes = size (name ());
|
|
469
|
+
if (actual_bytes) {
|
|
470
|
+
double actual_mb = actual_bytes / (double) (1 << 20);
|
|
471
|
+
MSG ("deflated to %zd bytes %.1f MB", actual_bytes, actual_mb);
|
|
472
|
+
MSG ("factor %.2f (%.2f%% compression)",
|
|
473
|
+
relative (written_bytes, actual_bytes),
|
|
474
|
+
percent (actual_bytes, written_bytes));
|
|
475
|
+
} else
|
|
476
|
+
MSG ("but could not determine actual size of written file");
|
|
477
|
+
}
|
|
478
|
+
} else {
|
|
479
|
+
uint64_t read_bytes = bytes ();
|
|
480
|
+
double read_mb = read_bytes / (double) (1 << 20);
|
|
481
|
+
MSG ("after reading %" PRIu64 " bytes %.1f MB", read_bytes, read_mb);
|
|
482
|
+
if (close_file == 2) {
|
|
483
|
+
size_t actual_bytes = size (name ());
|
|
484
|
+
double actual_mb = actual_bytes / (double) (1 << 20);
|
|
485
|
+
MSG ("inflated from %zd bytes %.1f MB", actual_bytes, actual_mb);
|
|
486
|
+
MSG ("factor %.2f (%.2f%% compression)",
|
|
487
|
+
relative (read_bytes, actual_bytes),
|
|
488
|
+
percent (actual_bytes, read_bytes));
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
#endif
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
void File::flush () {
|
|
496
|
+
assert (file);
|
|
497
|
+
fflush (file);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
File::~File () {
|
|
501
|
+
if (file)
|
|
502
|
+
close ();
|
|
503
|
+
free (_name);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
} // namespace CaDiCaL
|