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