| /***************************************************************************************[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 |