1 /***************************************************************************************[Options.h] 2 Copyright (c) 2008-2010, Niklas Sorensson 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 associated documentation files (the "Software"), to deal in the Software without restriction, 6 including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 furnished to do so, subject to the following conditions: 9 10 The above copyright notice and this permission notice shall be included in all copies or 11 substantial portions of the Software. 12 13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 **************************************************************************************************/ 19 20 #ifndef Minisat_Options_h 21 #define Minisat_Options_h 22 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <math.h> 26 #include <string.h> 27 28 #include "minisat/mtl/IntTypes.h" 29 #include "minisat/mtl/Vec.h" 30 #include "minisat/utils/ParseUtils.h" 31 32 namespace Minisat { 33 34 //================================================================================================== 35 // Top-level option parse/help functions: 36 37 38 extern void parseOptions (int& argc, char** argv, bool strict = false); 39 extern void printUsageAndExit(int argc, char** argv, bool verbose = false); 40 extern void setUsageHelp (const char* str); 41 extern void setHelpPrefixStr (const char* str); 42 43 44 //================================================================================================== 45 // Options is an abstract class that gives the interface for all types options: 46 47 48 class Option 49 { 50 protected: 51 const char* name; 52 const char* description; 53 const char* category; 54 const char* type_name; 55 getOptionList()56 static vec<Option*>& getOptionList () { static vec<Option*> options; return options; } getUsageString()57 static const char*& getUsageString() { static const char* usage_str; return usage_str; } getHelpPrefixString()58 static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; } 59 60 struct OptionLt { operatorOptionLt61 bool operator()(const Option* x, const Option* y) { 62 int test1 = strcmp(x->category, y->category); 63 return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0); 64 } 65 }; 66 Option(const char * name_,const char * desc_,const char * cate_,const char * type_)67 Option(const char* name_, 68 const char* desc_, 69 const char* cate_, 70 const char* type_) : 71 name (name_) 72 , description(desc_) 73 , category (cate_) 74 , type_name (type_) 75 { 76 getOptionList().push(this); 77 } 78 79 public: ~Option()80 virtual ~Option() {} 81 82 virtual bool parse (const char* str) = 0; 83 virtual void help (bool verbose = false) = 0; 84 85 friend void parseOptions (int& argc, char** argv, bool strict); 86 friend void printUsageAndExit (int argc, char** argv, bool verbose); 87 friend void setUsageHelp (const char* str); 88 friend void setHelpPrefixStr (const char* str); 89 }; 90 91 92 //================================================================================================== 93 // Range classes with specialization for floating types: 94 95 96 struct IntRange { 97 int begin; 98 int end; IntRangeIntRange99 IntRange(int b, int e) : begin(b), end(e) {} 100 }; 101 102 struct Int64Range { 103 int64_t begin; 104 int64_t end; Int64RangeInt64Range105 Int64Range(int64_t b, int64_t e) : begin(b), end(e) {} 106 }; 107 108 struct DoubleRange { 109 double begin; 110 double end; 111 bool begin_inclusive; 112 bool end_inclusive; DoubleRangeDoubleRange113 DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {} 114 }; 115 116 117 //================================================================================================== 118 // Double options: 119 120 121 class DoubleOption : public Option 122 { 123 protected: 124 DoubleRange range; 125 double value; 126 127 public: 128 DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false)) 129 : Option(n, d, c, "<double>"), range(r), value(def) { 130 // FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly. 131 } 132 133 operator double (void) const { return value; } 134 operator double& (void) { return value; } 135 DoubleOption& operator=(double x) { value = x; return *this; } 136 parse(const char * str)137 virtual bool parse(const char* str){ 138 const char* span = str; 139 140 if (!match(span, "-") || !match(span, name) || !match(span, "=")) 141 return false; 142 143 char* end; 144 double tmp = strtod(span, &end); 145 146 if (end == NULL) 147 return false; 148 else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){ 149 fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 150 exit(1); 151 }else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){ 152 fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 153 exit(1); } 154 155 value = tmp; 156 // fprintf(stderr, "READ VALUE: %g\n", value); 157 158 return true; 159 } 160 161 virtual void help (bool verbose = false){ 162 fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n", 163 name, type_name, 164 range.begin_inclusive ? '[' : '(', 165 range.begin, 166 range.end, 167 range.end_inclusive ? ']' : ')', 168 value); 169 if (verbose){ 170 fprintf(stderr, "\n %s\n", description); 171 fprintf(stderr, "\n"); 172 } 173 } 174 }; 175 176 177 //================================================================================================== 178 // Int options: 179 180 181 class IntOption : public Option 182 { 183 protected: 184 IntRange range; 185 int32_t value; 186 187 public: 188 IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX)) 189 : Option(n, d, c, "<int32>"), range(r), value(def) {} 190 int32_t(void)191 operator int32_t (void) const { return value; } 192 operator int32_t& (void) { return value; } 193 IntOption& operator= (int32_t x) { value = x; return *this; } 194 parse(const char * str)195 virtual bool parse(const char* str){ 196 const char* span = str; 197 198 if (!match(span, "-") || !match(span, name) || !match(span, "=")) 199 return false; 200 201 char* end; 202 int32_t tmp = strtol(span, &end, 10); 203 204 if (end == NULL) 205 return false; 206 else if (tmp > range.end){ 207 fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 208 exit(1); 209 }else if (tmp < range.begin){ 210 fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 211 exit(1); } 212 213 value = tmp; 214 215 return true; 216 } 217 218 virtual void help (bool verbose = false){ 219 fprintf(stderr, " -%-12s = %-8s [", name, type_name); 220 if (range.begin == INT32_MIN) 221 fprintf(stderr, "imin"); 222 else 223 fprintf(stderr, "%4d", range.begin); 224 225 fprintf(stderr, " .. "); 226 if (range.end == INT32_MAX) 227 fprintf(stderr, "imax"); 228 else 229 fprintf(stderr, "%4d", range.end); 230 231 fprintf(stderr, "] (default: %d)\n", value); 232 if (verbose){ 233 fprintf(stderr, "\n %s\n", description); 234 fprintf(stderr, "\n"); 235 } 236 } 237 }; 238 239 240 // Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll. 241 #ifndef _MSC_VER 242 243 class Int64Option : public Option 244 { 245 protected: 246 Int64Range range; 247 int64_t value; 248 249 public: 250 Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX)) 251 : Option(n, d, c, "<int64>"), range(r), value(def) {} 252 int64_t(void)253 operator int64_t (void) const { return value; } 254 operator int64_t& (void) { return value; } 255 Int64Option& operator= (int64_t x) { value = x; return *this; } 256 parse(const char * str)257 virtual bool parse(const char* str){ 258 const char* span = str; 259 260 if (!match(span, "-") || !match(span, name) || !match(span, "=")) 261 return false; 262 263 char* end; 264 int64_t tmp = strtoll(span, &end, 10); 265 266 if (end == NULL) 267 return false; 268 else if (tmp > range.end){ 269 fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 270 exit(1); 271 }else if (tmp < range.begin){ 272 fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 273 exit(1); } 274 275 value = tmp; 276 277 return true; 278 } 279 280 virtual void help (bool verbose = false){ 281 fprintf(stderr, " -%-12s = %-8s [", name, type_name); 282 if (range.begin == INT64_MIN) 283 fprintf(stderr, "imin"); 284 else 285 fprintf(stderr, "%4" PRIi64, range.begin); 286 287 fprintf(stderr, " .. "); 288 if (range.end == INT64_MAX) 289 fprintf(stderr, "imax"); 290 else 291 fprintf(stderr, "%4" PRIi64, range.end); 292 293 fprintf(stderr, "] (default: %" PRIi64")\n", value); 294 if (verbose){ 295 fprintf(stderr, "\n %s\n", description); 296 fprintf(stderr, "\n"); 297 } 298 } 299 }; 300 #endif 301 302 //================================================================================================== 303 // String option: 304 305 306 class StringOption : public Option 307 { 308 const char* value; 309 public: 310 StringOption(const char* c, const char* n, const char* d, const char* def = NULL) 311 : Option(n, d, c, "<string>"), value(def) {} 312 313 operator const char* (void) const { return value; } 314 operator const char*& (void) { return value; } 315 StringOption& operator= (const char* x) { value = x; return *this; } 316 parse(const char * str)317 virtual bool parse(const char* str){ 318 const char* span = str; 319 320 if (!match(span, "-") || !match(span, name) || !match(span, "=")) 321 return false; 322 323 value = span; 324 return true; 325 } 326 327 virtual void help (bool verbose = false){ 328 fprintf(stderr, " -%-10s = %8s\n", name, type_name); 329 if (verbose){ 330 fprintf(stderr, "\n %s\n", description); 331 fprintf(stderr, "\n"); 332 } 333 } 334 }; 335 336 337 //================================================================================================== 338 // Bool option: 339 340 341 class BoolOption : public Option 342 { 343 bool value; 344 345 public: BoolOption(const char * c,const char * n,const char * d,bool v)346 BoolOption(const char* c, const char* n, const char* d, bool v) 347 : Option(n, d, c, "<bool>"), value(v) {} 348 349 operator bool (void) const { return value; } 350 operator bool& (void) { return value; } 351 BoolOption& operator=(bool b) { value = b; return *this; } 352 parse(const char * str)353 virtual bool parse(const char* str){ 354 const char* span = str; 355 356 if (match(span, "-")){ 357 bool b = !match(span, "no-"); 358 359 if (strcmp(span, name) == 0){ 360 value = b; 361 return true; } 362 } 363 364 return false; 365 } 366 367 virtual void help (bool verbose = false){ 368 369 fprintf(stderr, " -%s, -no-%s", name, name); 370 371 for (uint32_t i = 0; i < 32 - strlen(name)*2; i++) 372 fprintf(stderr, " "); 373 374 fprintf(stderr, " "); 375 fprintf(stderr, "(default: %s)\n", value ? "on" : "off"); 376 if (verbose){ 377 fprintf(stderr, "\n %s\n", description); 378 fprintf(stderr, "\n"); 379 } 380 } 381 }; 382 383 //================================================================================================= 384 } 385 386 #endif 387