387 lines
12 KiB
C
387 lines
12 KiB
C
|
/***************************************************************************************[Options.h]
|
||
|
Copyright (c) 2008-2010, Niklas Sorensson
|
||
|
|
||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||
|
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||
|
furnished to do so, subject to the following conditions:
|
||
|
|
||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||
|
substantial portions of the Software.
|
||
|
|
||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||
|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||
|
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
**************************************************************************************************/
|
||
|
|
||
|
#ifndef Minisat_Options_h
|
||
|
#define Minisat_Options_h
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <math.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "IntTypes.h"
|
||
|
#include "Vec.h"
|
||
|
#include "ParseUtils.h"
|
||
|
|
||
|
namespace Minisat {
|
||
|
|
||
|
//==================================================================================================
|
||
|
// Top-level option parse/help functions:
|
||
|
|
||
|
|
||
|
extern void parseOptions (int& argc, char** argv, bool strict = false);
|
||
|
extern void printUsageAndExit(int argc, char** argv, bool verbose = false);
|
||
|
extern void setUsageHelp (const char* str);
|
||
|
extern void setHelpPrefixStr (const char* str);
|
||
|
|
||
|
|
||
|
//==================================================================================================
|
||
|
// Options is an abstract class that gives the interface for all types options:
|
||
|
|
||
|
|
||
|
class Option
|
||
|
{
|
||
|
protected:
|
||
|
const char* name;
|
||
|
const char* description;
|
||
|
const char* category;
|
||
|
const char* type_name;
|
||
|
|
||
|
static vec<Option*>& getOptionList () { static vec<Option*> options; return options; }
|
||
|
static const char*& getUsageString() { static const char* usage_str; return usage_str; }
|
||
|
static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; }
|
||
|
|
||
|
struct OptionLt {
|
||
|
bool operator()(const Option* x, const Option* y) {
|
||
|
int test1 = strcmp(x->category, y->category);
|
||
|
return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Option(const char* name_,
|
||
|
const char* desc_,
|
||
|
const char* cate_,
|
||
|
const char* type_) :
|
||
|
name (name_)
|
||
|
, description(desc_)
|
||
|
, category (cate_)
|
||
|
, type_name (type_)
|
||
|
{
|
||
|
getOptionList().push(this);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
virtual ~Option() {}
|
||
|
|
||
|
virtual bool parse (const char* str) = 0;
|
||
|
virtual void help (bool verbose = false) = 0;
|
||
|
|
||
|
friend void parseOptions (int& argc, char** argv, bool strict);
|
||
|
friend void printUsageAndExit (int argc, char** argv, bool verbose);
|
||
|
friend void setUsageHelp (const char* str);
|
||
|
friend void setHelpPrefixStr (const char* str);
|
||
|
};
|
||
|
|
||
|
|
||
|
//==================================================================================================
|
||
|
// Range classes with specialization for floating types:
|
||
|
|
||
|
|
||
|
struct IntRange {
|
||
|
int begin;
|
||
|
int end;
|
||
|
IntRange(int b, int e) : begin(b), end(e) {}
|
||
|
};
|
||
|
|
||
|
struct Int64Range {
|
||
|
int64_t begin;
|
||
|
int64_t end;
|
||
|
Int64Range(int64_t b, int64_t e) : begin(b), end(e) {}
|
||
|
};
|
||
|
|
||
|
struct DoubleRange {
|
||
|
double begin;
|
||
|
double end;
|
||
|
bool begin_inclusive;
|
||
|
bool end_inclusive;
|
||
|
DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {}
|
||
|
};
|
||
|
|
||
|
|
||
|
//==================================================================================================
|
||
|
// Double options:
|
||
|
|
||
|
|
||
|
class DoubleOption : public Option
|
||
|
{
|
||
|
protected:
|
||
|
DoubleRange range;
|
||
|
double value;
|
||
|
|
||
|
public:
|
||
|
DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false))
|
||
|
: Option(n, d, c, "<double>"), range(r), value(def) {
|
||
|
// FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly.
|
||
|
}
|
||
|
|
||
|
operator double (void) const { return value; }
|
||
|
operator double& (void) { return value; }
|
||
|
DoubleOption& operator=(double x) { value = x; return *this; }
|
||
|
|
||
|
virtual bool parse(const char* str){
|
||
|
const char* span = str;
|
||
|
|
||
|
if (!match(span, "-") || !match(span, name) || !match(span, "="))
|
||
|
return false;
|
||
|
|
||
|
char* end;
|
||
|
double tmp = strtod(span, &end);
|
||
|
|
||
|
if (end == NULL)
|
||
|
return false;
|
||
|
else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){
|
||
|
fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name);
|
||
|
exit(1);
|
||
|
}else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){
|
||
|
fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name);
|
||
|
exit(1); }
|
||
|
|
||
|
value = tmp;
|
||
|
// fprintf(stderr, "READ VALUE: %g\n", value);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void help (bool verbose = false){
|
||
|
fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n",
|
||
|
name, type_name,
|
||
|
range.begin_inclusive ? '[' : '(',
|
||
|
range.begin,
|
||
|
range.end,
|
||
|
range.end_inclusive ? ']' : ')',
|
||
|
value);
|
||
|
if (verbose){
|
||
|
fprintf(stderr, "\n %s\n", description);
|
||
|
fprintf(stderr, "\n");
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
//==================================================================================================
|
||
|
// Int options:
|
||
|
|
||
|
|
||
|
class IntOption : public Option
|
||
|
{
|
||
|
protected:
|
||
|
IntRange range;
|
||
|
int32_t value;
|
||
|
|
||
|
public:
|
||
|
IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX))
|
||
|
: Option(n, d, c, "<int32>"), range(r), value(def) {}
|
||
|
|
||
|
operator int32_t (void) const { return value; }
|
||
|
operator int32_t& (void) { return value; }
|
||
|
IntOption& operator= (int32_t x) { value = x; return *this; }
|
||
|
|
||
|
virtual bool parse(const char* str){
|
||
|
const char* span = str;
|
||
|
|
||
|
if (!match(span, "-") || !match(span, name) || !match(span, "="))
|
||
|
return false;
|
||
|
|
||
|
char* end;
|
||
|
int32_t tmp = strtol(span, &end, 10);
|
||
|
|
||
|
if (end == NULL)
|
||
|
return false;
|
||
|
else if (tmp > range.end){
|
||
|
fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name);
|
||
|
exit(1);
|
||
|
}else if (tmp < range.begin){
|
||
|
fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name);
|
||
|
exit(1); }
|
||
|
|
||
|
value = tmp;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void help (bool verbose = false){
|
||
|
fprintf(stderr, " -%-12s = %-8s [", name, type_name);
|
||
|
if (range.begin == INT32_MIN)
|
||
|
fprintf(stderr, "imin");
|
||
|
else
|
||
|
fprintf(stderr, "%4d", range.begin);
|
||
|
|
||
|
fprintf(stderr, " .. ");
|
||
|
if (range.end == INT32_MAX)
|
||
|
fprintf(stderr, "imax");
|
||
|
else
|
||
|
fprintf(stderr, "%4d", range.end);
|
||
|
|
||
|
fprintf(stderr, "] (default: %d)\n", value);
|
||
|
if (verbose){
|
||
|
fprintf(stderr, "\n %s\n", description);
|
||
|
fprintf(stderr, "\n");
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
// Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll.
|
||
|
#ifndef _MSC_VER
|
||
|
|
||
|
class Int64Option : public Option
|
||
|
{
|
||
|
protected:
|
||
|
Int64Range range;
|
||
|
int64_t value;
|
||
|
|
||
|
public:
|
||
|
Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX))
|
||
|
: Option(n, d, c, "<int64>"), range(r), value(def) {}
|
||
|
|
||
|
operator int64_t (void) const { return value; }
|
||
|
operator int64_t& (void) { return value; }
|
||
|
Int64Option& operator= (int64_t x) { value = x; return *this; }
|
||
|
|
||
|
virtual bool parse(const char* str){
|
||
|
const char* span = str;
|
||
|
|
||
|
if (!match(span, "-") || !match(span, name) || !match(span, "="))
|
||
|
return false;
|
||
|
|
||
|
char* end;
|
||
|
int64_t tmp = strtoll(span, &end, 10);
|
||
|
|
||
|
if (end == NULL)
|
||
|
return false;
|
||
|
else if (tmp > range.end){
|
||
|
fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name);
|
||
|
exit(1);
|
||
|
}else if (tmp < range.begin){
|
||
|
fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name);
|
||
|
exit(1); }
|
||
|
|
||
|
value = tmp;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void help (bool verbose = false){
|
||
|
fprintf(stderr, " -%-12s = %-8s [", name, type_name);
|
||
|
if (range.begin == INT64_MIN)
|
||
|
fprintf(stderr, "imin");
|
||
|
else
|
||
|
fprintf(stderr, "%4" PRIi64 , range.begin);
|
||
|
|
||
|
fprintf(stderr, " .. ");
|
||
|
if (range.end == INT64_MAX)
|
||
|
fprintf(stderr, "imax");
|
||
|
else
|
||
|
fprintf(stderr, "%4" PRIi64 , range.end);
|
||
|
|
||
|
fprintf(stderr, "] (default: %" PRIi64 ")\n", value);
|
||
|
if (verbose){
|
||
|
fprintf(stderr, "\n %s\n", description);
|
||
|
fprintf(stderr, "\n");
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
//==================================================================================================
|
||
|
// String option:
|
||
|
|
||
|
|
||
|
class StringOption : public Option
|
||
|
{
|
||
|
const char* value;
|
||
|
public:
|
||
|
StringOption(const char* c, const char* n, const char* d, const char* def = NULL)
|
||
|
: Option(n, d, c, "<string>"), value(def) {}
|
||
|
|
||
|
operator const char* (void) const { return value; }
|
||
|
operator const char*& (void) { return value; }
|
||
|
StringOption& operator= (const char* x) { value = x; return *this; }
|
||
|
|
||
|
virtual bool parse(const char* str){
|
||
|
const char* span = str;
|
||
|
|
||
|
if (!match(span, "-") || !match(span, name) || !match(span, "="))
|
||
|
return false;
|
||
|
|
||
|
value = span;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void help (bool verbose = false){
|
||
|
fprintf(stderr, " -%-10s = %8s\n", name, type_name);
|
||
|
if (verbose){
|
||
|
fprintf(stderr, "\n %s\n", description);
|
||
|
fprintf(stderr, "\n");
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
//==================================================================================================
|
||
|
// Bool option:
|
||
|
|
||
|
|
||
|
class BoolOption : public Option
|
||
|
{
|
||
|
bool value;
|
||
|
|
||
|
public:
|
||
|
BoolOption(const char* c, const char* n, const char* d, bool v)
|
||
|
: Option(n, d, c, "<bool>"), value(v) {}
|
||
|
|
||
|
operator bool (void) const { return value; }
|
||
|
operator bool& (void) { return value; }
|
||
|
BoolOption& operator=(bool b) { value = b; return *this; }
|
||
|
|
||
|
virtual bool parse(const char* str){
|
||
|
const char* span = str;
|
||
|
|
||
|
if (match(span, "-")){
|
||
|
bool b = !match(span, "no-");
|
||
|
|
||
|
if (strcmp(span, name) == 0){
|
||
|
value = b;
|
||
|
return true; }
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
virtual void help (bool verbose = false){
|
||
|
|
||
|
fprintf(stderr, " -%s, -no-%s", name, name);
|
||
|
|
||
|
for (uint32_t i = 0; i < 32 - strlen(name)*2; i++)
|
||
|
fprintf(stderr, " ");
|
||
|
|
||
|
fprintf(stderr, " ");
|
||
|
fprintf(stderr, "(default: %s)\n", value ? "on" : "off");
|
||
|
if (verbose){
|
||
|
fprintf(stderr, "\n %s\n", description);
|
||
|
fprintf(stderr, "\n");
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//=================================================================================================
|
||
|
}
|
||
|
|
||
|
#endif
|