ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
kptions.c
Go to the documentation of this file.
1#include "options.h"
2#include "error.h"
3#include "print.h"
4
5#include <ctype.h>
6#include <limits.h>
7#include <stdarg.h>
8#include <stdio.h>
9#include <string.h>
10
12
13#ifdef KISSAT_NOPTIONS
14
15static const opt table[] = {
16#define OPTION(N, V, L, H, D) {#N, (int) (V), D},
18#undef OPTION
19};
20
21#else
22
23static const opt table[] = {
24#define OPTION(N, V, L, H, D) {#N, (int) (V), (int) (L), (int) (H), D},
26#undef OPTION
27};
28
29#endif
30
31#define size_table (sizeof table / sizeof *table)
32
35
36static void check_table_sorted (void) {
37#ifndef KISSAT_NDEBUG
38 opt const *p = 0;
39 for (all_options (o))
40 if (p && strcmp (p->name, o->name) >= 0)
41 kissat_fatal ("option '%s' before option '%s'", p->name, o->name);
42 else
43 p = o;
44#endif
45}
46
47const opt *kissat_options_has (const char *name) {
48 size_t l = 0, m, r = size_table;
49 int tmp;
50 opt const *o;
51 KISSAT_assert (l < r);
52 while (l + 1 < r) {
53 m = l + (r - l) / 2;
54 tmp = strcmp (name, (o = table + m)->name);
55 if (tmp < 0)
56 r = m;
57 else if (tmp > 0)
58 l = m;
59 else
60 return o;
61 }
62 o = table + l;
63 tmp = strcmp (o->name, name);
64 return tmp ? 0 : o;
65}
66
67bool kissat_parse_option_value (const char *val_str, int *res_ptr) {
68 if (!strcmp (val_str, "true")) {
69 *res_ptr = 1;
70 return true;
71 }
72 if (!strcmp (val_str, "false")) {
73 *res_ptr = 0;
74 return true;
75 }
76 int sign = 1;
77 char const *p = val_str;
78 int ch = *p++;
79 if (ch == '-') {
80 sign = -1;
81 ch = *p++;
82 }
83 if (!isdigit (ch)) // at least one digit
84 return false;
85 const unsigned max = -(unsigned) INT_MIN;
86 unsigned res = ch - '0';
87 while (isdigit ((ch = *p++))) {
88 if (max / 10 < res)
89 return false;
90 res *= 10;
91 const unsigned digit = ch - '0';
92 if (max - digit < res)
93 return false;
94 res += digit;
95 if (!res)
96 return false; // invalid '00'
97 }
98 if (ch == 'e') // parse '13e5' etc.
99 {
100 if (!isdigit ((ch = *p++))) // at least one digit
101 return false;
102 if (res) {
103 if (*p) // exactly one digit
104 return false;
105 const unsigned digit = ch - '0';
106 for (unsigned i = 0; i < digit; i++) {
107 if (max / 10 < res)
108 return false;
109 res *= 10;
110 }
111 } else // parse '0^123123123' etc.
112 {
113 while (isdigit (ch = *p++)) // arbitrary many digits
114 ;
115 if (ch)
116 return false;
117 }
118 } else if (ch == '^') // parse '2^11' etc.
119 {
120 const unsigned base = res;
121 if (!isdigit ((ch = *p++))) // at least one digit
122 return false;
123 unsigned exp = ch - '0';
124 if (base < 2) // parse '0^123123123' etc.
125 {
126 while (isdigit (ch = *p++)) // arbitrary many digits
127 ;
128 if (ch)
129 return false;
130 } else if (isdigit (ch = *p++)) // parse '2^30' etc.
131 {
132 if (*p) // at most two digits
133 return false;
134 exp *= 10;
135 const unsigned digit = ch - '0';
136 exp += digit;
137 if (!exp) // '2^00' invalid
138 return false;
139 } else if (ch)
140 return false;
141 if (exp)
142 for (unsigned i = 1; i < exp; i++) {
143 if (max / base < res)
144 return false;
145 res *= base;
146 }
147 else if (base)
148 res = 1; // parse '3^0'
149 else
150 return false; // '0^0' invalid
151 } else if (ch)
152 return false;
153 KISSAT_assert (res <= max);
154 if (sign > 0 && res == max)
155 return false;
156 res *= sign;
157 *res_ptr = res;
158 return true;
159}
160
161const char *kissat_parse_option_name (const char *arg, const char *name) {
162 if (arg[0] != '-' || arg[1] != '-')
163 return 0;
164 char const *p = arg + 2, *q = name;
165 if (p[0] == 'n' && p[1] == 'o' && p[2] == '-')
166 return strcmp (p + 3, name) ? 0 : "0";
167 while (*p && *p == *q)
168 p++, q++;
169 if (*q)
170 return 0;
171 if (*p != '=')
172 return 0;
173 return p + 1;
174}
175
176#ifdef KISSAT_NOPTIONS
177
178void kissat_init_options (void) { check_table_sorted (); }
179
180int kissat_options_get (const char *name) {
181 const opt *const o = kissat_options_has (name);
182 return o ? o->value : 0;
183}
184
185#else
186
188
189#include "format.h"
190
191#include <assert.h>
192#include <stdbool.h>
193#include <stdlib.h>
194
196
197static void kissat_printf_usage (const char *option, const char *fmt, ...) {
198 va_list ap;
199 printf (" %-26s ", option);
200 va_start (ap, fmt);
201 vprintf (fmt, ap);
202 va_end (ap);
203 fputc ('\n', stdout);
204}
205
206static void check_ranges (void) {
207#define OPTION(N, V, L, H, D) \
208 do { \
209 if ((int) (L) > (int) (H)) \
210 kissat_fatal ("minimum '%d' of option '%s' above maximum '%d'", \
211 (int) (L), #N, (int) (H)); \
212 if ((int) (V) < (int) (L)) \
213 kissat_fatal ( \
214 "default value '%d' of option '%s' below minimum '%d'", \
215 (int) (V), #N, (int) (L)); \
216 if ((int) (V) > (int) (H)) \
217 kissat_fatal ( \
218 "default value '%d' of option '%s' above maximum '%d'", \
219 (int) (V), #N, (int) (H)); \
220 } while (0);
221 OPTIONS
222#undef OPTION
223}
224
225static void check_name_length (void) {
226#ifndef KISSAT_NDEBUG
227#define OPTION(N, V, L, H, D) \
228 if (strlen (#N) + 1 > kissat_options_max_name_buffer_size) \
229 kissat_fatal ("option '%s' name length %zu " \
230 "exceeds maximum name buffer size %zu", \
231 #N, strlen (#N), kissat_options_max_name_buffer_size);
232 OPTIONS
233#undef OPTION
234#endif
235}
236
237int kissat_options_get (const options *options, const char *name) {
238 const int *const p =
239 kissat_options_ref (options, kissat_options_has (name));
240 return p ? *p : 0;
241}
242
243int kissat_options_set_opt (options *options, const opt *o, int value) {
246 int *p = (int *) options + (o - table);
247 int res = *p;
248 if (value == res)
249 return res;
250 if (value < o->low)
251 value = o->low;
252 if (value > o->high)
253 value = o->high;
254 *p = value;
255 return res;
256}
257
258int kissat_options_set (options *options, const char *name, int value) {
259 const opt *const o = kissat_options_has (name);
260 if (!o)
261 return 0;
262 return kissat_options_set_opt (options, o, value);
263}
264
265void kissat_init_options (options *options) {
266 check_ranges ();
267 check_name_length ();
268 check_table_sorted ();
269#define OPTION(N, V, L, H, D) \
270 KISSAT_assert ((L) <= (V)); \
271 KISSAT_assert ((V) <= (H)); \
272 options->N = (V);
273 OPTIONS
274#undef OPTION
275}
276
277#define FORMAT_OPTION_LIMIT(V) \
278 (((V) == INT_MIN || (V) == INT_MAX) \
279 ? "." \
280 : kissat_format_value (&format, false, (V)))
281
282void kissat_options_usage (void) {
283 check_ranges ();
284 check_name_length ();
285 check_table_sorted ();
286 format format;
287 memset (&format, 0, sizeof format);
288#define OPTION(N, V, L, H, D) \
289 do { \
290 const bool b = ((L) == 0 && (H) == 1); \
291 char buffer[96]; \
292 if (b) \
293 sprintf (buffer, "--%s=<bool>", #N); \
294 else { \
295 const char *low_str = FORMAT_OPTION_LIMIT ((L)); \
296 const char *high_str = FORMAT_OPTION_LIMIT ((H)); \
297 sprintf (buffer, "--%s=%s..%s", #N, low_str, high_str); \
298 } \
299 const char *val_str = kissat_format_value (&format, b, (V)); \
300 kissat_printf_usage (buffer, "%s [%s]", D, val_str); \
301 } while (0);
302 OPTIONS
303#undef OPTION
304}
305
306bool kissat_options_parse_arg (const char *arg, char *buffer,
307 int *val_ptr) {
308 if (arg[0] != '-' || arg[1] != '-')
309 return false;
310 char const *name = arg + 2, *p = name;
311 int ch;
312 while ((ch = *p) && ch != '=')
313 p++;
314 if (ch) {
315 KISSAT_assert (ch == '=');
316 const size_t len = p - name;
317 if (len >= kissat_options_max_name_buffer_size)
318 return false;
319 memcpy (buffer, name, len);
320 buffer[len] = 0;
321 const opt *const o = kissat_options_has (buffer);
322 if (!o)
323 return false;
324 int value;
325 if (!kissat_parse_option_value (p + 1, &value))
326 return false;
327 if (value < o->low || value > o->high)
328 return false;
329 *val_ptr = value;
330 } else {
331 int value = 0;
332 if (arg[2] == 'n' && arg[3] == 'o' && arg[4] == '-') {
333 name += 3;
334 const opt *const o = kissat_options_has (name);
335 if (!o || o->low > (value = 0))
336 return false;
337 } else {
338 const opt *const o = kissat_options_has (name);
339 if (!o || o->high < (value = 1))
340 return false;
341 }
342 KISSAT_assert (strlen (name) < kissat_options_max_name_buffer_size);
343 strcpy (buffer, name);
344 *val_ptr = value;
345 }
346 return true;
347}
348
349static bool ignore_embedded_option_for_fuzzing (const char *name) {
350#ifdef EMBEDDED
351 if (!strcmp (name, "embedded"))
352 return true;
353#endif
354#ifndef KISSAT_QUIET
355 if (!strcmp (name, "quiet"))
356 return true;
357#endif
358 (void) name;
359 return false;
360}
361
362void kissat_print_embedded_option_list () {
363#define OPTION(N, V, L, H, D) \
364 if (!ignore_embedded_option_for_fuzzing (#N)) \
365 printf ("c --%s=%d\n", #N, (int) (V));
366 OPTIONS
367#undef OPTION
368}
369
370static bool ignore_range_option_for_fuzzing (const char *name) {
371#ifdef LOGGING
372 if (!strcmp (name, "log"))
373 return true;
374#endif
375#ifdef EMBEDDED
376 if (!strcmp (name, "embedded"))
377 return true;
378#endif
379#ifndef KISSAT_QUIET
380 if (!strcmp (name, "quiet"))
381 return true;
382#endif
383 if (!strcmp (name, "reduce"))
384 return true;
385 if (!strcmp (name, "reluctant"))
386 return true;
387 if (!strcmp (name, "rephase"))
388 return true;
389 if (!strcmp (name, "restart"))
390 return true;
391 return false;
392}
393
394void kissat_print_option_range_list (void) {
395#define OPTION(N, V, L, H, D) \
396 if (!ignore_range_option_for_fuzzing (#N)) \
397 printf ("%s %d %d %d\n", #N, (int) (L), (int) (V), (int) (H));
398 OPTIONS
399#undef OPTION
400}
401
402#endif
403
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
ABC_NAMESPACE_IMPL_START typedef signed char value
void kissat_fatal(const char *fmt,...)
Definition error.c:58
Cube * p
Definition exorList.c:222
#define vprintf
Definition fretime.h:138
#define KISSAT_assert(ignore)
Definition global.h:13
const opt * kissat_options_end
Definition kptions.c:34
void kissat_init_options(void)
Definition kptions.c:178
int kissat_options_get(const char *name)
Definition kptions.c:180
#define size_table
Definition kptions.c:31
const opt * kissat_options_begin
Definition kptions.c:33
const opt * kissat_options_has(const char *name)
Definition kptions.c:47
bool kissat_parse_option_value(const char *val_str, int *res_ptr)
Definition kptions.c:67
const char * kissat_parse_option_name(const char *arg, const char *name)
Definition kptions.c:161
char * name
Definition main.h:24
#define all_options(O)
Definition options.h:243
#define OPTIONS
Definition options.hpp:24
Definition options.h:228
const char * name
Definition options.h:229
const int value
Definition options.h:235
char * memcpy()
char * memset()
int strlen()
int strcmp()
char * strcpy()