WvStreams
|
00001 /* -*- Mode: C++ -*- 00002 * Copyright (C) 2004-2005 Net Integration Technologies, Inc. 00003 * 00004 * WvStreams interface for command-line argument processing 00005 */ 00006 00007 #include "wvargs.h" 00008 #include "wvscatterhash.h" 00009 00010 // Some screwy defines that show up in _WIN32 and cause problems 00011 #undef error_t 00012 #undef __error_t_defined 00013 #undef argc 00014 #undef argv 00015 #undef __argc 00016 #undef __argv 00017 00018 #include <argp.h> 00019 #include <limits.h> 00020 00021 00022 class WvArgsOption 00023 { 00024 public: 00025 00026 int short_option; 00027 WvString long_option; 00028 WvString desc; 00029 00030 WvArgsOption(int _short_option, 00031 WvStringParm _long_option, 00032 WvStringParm _desc) 00033 : short_option(_short_option), long_option(_long_option), desc(_desc) 00034 { 00035 } 00036 00037 virtual ~WvArgsOption() 00038 { 00039 } 00040 00041 virtual WvString process(WvStringParm arg) 00042 { 00043 return WvString::null; 00044 } 00045 00046 virtual void add_to_argp(WvArgsData &data); 00047 }; 00048 00049 00050 DeclareWvList(WvArgsOption); 00051 DeclareWvScatterDict(WvArgsOption, int, short_option); 00052 00053 class WvArgsData 00054 { 00055 public: 00056 WvArgsData(); 00057 ~WvArgsData(); 00058 00059 argp_option *argp() const; 00060 void *self() const; 00061 00062 void add(WvArgsOption *option); 00063 void remove(char short_option, WvStringParm long_option); 00064 void zap(); 00065 00066 void add_required_arg(); 00067 void subtract_required_arg(); 00068 const WvStringList &args() const; 00069 00070 static error_t parser(int key, char *arg, argp_state *state); 00071 00072 unsigned int flags; 00073 00074 protected: 00075 friend class WvArgsOption; 00076 friend class WvArgsArgOption; 00077 friend class WvArgs; 00078 00079 void argp_build(); 00080 bool argp_add(const char *name, int key, const char *arg, int flags, 00081 const char *doc, int group); 00082 private: 00083 void argp_init(size_t size = 0); 00084 00085 bool argp_add(const argp_option &option); 00086 bool argp_double(); 00087 00088 argp_option *argp_; 00089 size_t argp_index; // Last element in the options array 00090 size_t argp_size; // Size of the options array 00091 00092 // I create two data-structures, only one of them actually owning 00093 // the objects, of course. The List is for ordered construction 00094 // of argp_. The Dict is for constant-time lookups when 00095 // process()ing options. 00096 WvArgsOptionList options_list; // An ordered list of WvArgsOptions 00097 WvArgsOptionDict options_dict; // A constant-time lookup of them 00098 00099 WvStringList args_; // Arguments after all options have been parsed 00100 size_t required_args; // Number of these mandatory arguments. 00101 size_t maximum_args; // Number of maximum arguments. 00102 00103 int last_no_key; // Last key for options with no short_option 00104 }; 00105 00106 00107 void WvArgsOption::add_to_argp(WvArgsData &data) 00108 { 00109 data.argp_add(long_option, short_option, 0, 0, desc, 0); 00110 } 00111 00112 00113 class WvArgsNoArgOption : public WvArgsOption 00114 { 00115 00116 public: 00117 00118 WvArgsNoArgOption(int _short_option, 00119 WvStringParm _long_option, 00120 WvStringParm _desc) 00121 : WvArgsOption(_short_option, _long_option, _desc) 00122 { 00123 } 00124 }; 00125 00126 00127 class WvArgsSetBoolOption : public WvArgsNoArgOption 00128 { 00129 00130 private: 00131 00132 bool &flag; 00133 00134 public: 00135 00136 WvArgsSetBoolOption(int _short_option, 00137 WvStringParm _long_option, 00138 WvStringParm _desc, 00139 bool &_flag) 00140 : WvArgsNoArgOption(_short_option, _long_option, _desc), 00141 flag(_flag) 00142 { 00143 } 00144 00145 virtual WvString process(WvStringParm arg) 00146 { 00147 flag = true; 00148 return WvString::null; 00149 } 00150 }; 00151 00152 00153 class WvArgsResetBoolOption : public WvArgsNoArgOption 00154 { 00155 00156 private: 00157 00158 bool &flag; 00159 00160 public: 00161 00162 WvArgsResetBoolOption(int _short_option, 00163 WvStringParm _long_option, 00164 WvStringParm _desc, 00165 bool &_flag) 00166 : WvArgsNoArgOption(_short_option, _long_option, _desc), 00167 flag(_flag) 00168 { 00169 } 00170 00171 virtual WvString process(WvStringParm arg) 00172 { 00173 flag = false; 00174 return WvString::null; 00175 } 00176 }; 00177 00178 00179 class WvArgsFlipBoolOption : public WvArgsNoArgOption 00180 { 00181 00182 private: 00183 00184 bool &flag; 00185 00186 public: 00187 00188 WvArgsFlipBoolOption(int _short_option, 00189 WvStringParm _long_option, 00190 WvStringParm _desc, 00191 bool &_flag) 00192 : WvArgsNoArgOption(_short_option, _long_option, _desc), 00193 flag(_flag) 00194 { 00195 } 00196 00197 virtual WvString process(WvStringParm arg) 00198 { 00199 flag = !flag; 00200 return WvString::null; 00201 } 00202 }; 00203 00204 00205 class WvArgsIncIntOption : public WvArgsNoArgOption 00206 { 00207 private: 00208 int &val; 00209 00210 public: 00211 WvArgsIncIntOption(int _short_option, 00212 WvStringParm _long_option, 00213 WvStringParm _desc, 00214 int &_val) 00215 : WvArgsNoArgOption(_short_option, _long_option, _desc), 00216 val(_val) 00217 { 00218 } 00219 00220 virtual WvString process(WvStringParm arg) 00221 { 00222 val++; 00223 return WvString::null; 00224 } 00225 }; 00226 00227 00228 class WvArgsNoArgCallbackOption : public WvArgsNoArgOption 00229 { 00230 00231 private: 00232 00233 WvArgs::NoArgCallback cb; 00234 void *ud; 00235 00236 public: 00237 00238 WvArgsNoArgCallbackOption(int _short_option, 00239 WvStringParm _long_option, 00240 WvStringParm _desc, 00241 WvArgs::NoArgCallback _cb, 00242 void *_ud) 00243 : WvArgsNoArgOption(_short_option, _long_option, _desc), 00244 cb(_cb), ud(_ud) 00245 { 00246 } 00247 00248 virtual WvString process(WvStringParm arg) 00249 { 00250 if (cb(ud)) 00251 return WvString::null; 00252 else 00253 return WvString("invalid option `%s'", arg); 00254 } 00255 }; 00256 00257 00258 class WvArgsArgOption : public WvArgsOption 00259 { 00260 private: 00261 00262 WvString arg_desc; 00263 00264 public: 00265 00266 WvArgsArgOption(int _short_option, 00267 WvStringParm _long_option, 00268 WvStringParm _desc, 00269 WvStringParm _arg_desc) 00270 : WvArgsOption(_short_option, _long_option, _desc), 00271 arg_desc(_arg_desc) 00272 { 00273 } 00274 00275 virtual void add_to_argp(WvArgsData &data) 00276 { 00277 data.argp_add(long_option, short_option, arg_desc, 0, desc, 0); 00278 } 00279 }; 00280 00281 00282 class WvArgsIntOption : public WvArgsArgOption 00283 { 00284 private: 00285 00286 int &val; 00287 00288 public: 00289 00290 WvArgsIntOption(int _short_option, 00291 WvStringParm _long_option, 00292 WvStringParm _desc, 00293 WvStringParm _arg_desc, 00294 int &_val) 00295 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00296 val(_val) 00297 { 00298 } 00299 00300 virtual WvString process(WvStringParm arg) 00301 { 00302 char *tailptr = NULL; 00303 errno = 0; 00304 long int tmp = strtol(arg, &tailptr, 10); 00305 if (errno == ERANGE || tmp > INT_MAX || tmp < INT_MIN ) 00306 { 00307 // Out of range 00308 return WvString("`%s': invalid number.", arg); 00309 } 00310 else if (*tailptr) 00311 { 00312 // Invalid number 00313 return WvString("`%s': invalid number.", arg); 00314 } 00315 else 00316 { 00317 val = tmp; 00318 return WvString::null; 00319 } 00320 } 00321 }; 00322 00323 00324 class WvArgsLongOption : public WvArgsArgOption 00325 { 00326 private: 00327 00328 long &val; 00329 00330 public: 00331 00332 WvArgsLongOption(int _short_option, 00333 WvStringParm _long_option, 00334 WvStringParm _desc, 00335 WvStringParm _arg_desc, 00336 long &_val) 00337 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00338 val(_val) 00339 { 00340 } 00341 00342 virtual WvString process(WvStringParm arg) 00343 { 00344 char *tailptr = NULL; 00345 errno = 0; 00346 long int tmp = strtol(arg, &tailptr, 10); 00347 if (errno == ERANGE) 00348 { 00349 // Out of range 00350 return WvString("`%s': invalid number.", arg); 00351 } 00352 else if (*tailptr) 00353 { 00354 // Invalid number 00355 return WvString("`%s': invalid number.", arg); 00356 } 00357 else 00358 { 00359 val = tmp; 00360 return WvString::null; 00361 } 00362 } 00363 }; 00364 00365 00366 class WvArgsFloatOption : public WvArgsArgOption 00367 { 00368 private: 00369 00370 float &val; 00371 00372 public: 00373 00374 WvArgsFloatOption(int _short_option, 00375 WvStringParm _long_option, 00376 WvStringParm _desc, 00377 WvStringParm _arg_desc, 00378 float &_val) 00379 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00380 val(_val) 00381 { 00382 } 00383 00384 virtual WvString process(WvStringParm arg) 00385 { 00386 char *tailptr = NULL; 00387 errno = 0; 00388 float tmp = strtof(arg, &tailptr); 00389 if (errno == ERANGE) 00390 { 00391 // Out of range 00392 return WvString("`%s': invalid number.", arg); 00393 } 00394 else if (*tailptr) 00395 { 00396 // Invalid number 00397 return WvString("`%s': invalid number.", arg); 00398 } 00399 else 00400 { 00401 val = tmp; 00402 return WvString::null; 00403 } 00404 } 00405 }; 00406 00407 00408 class WvArgsDoubleOption : public WvArgsArgOption 00409 { 00410 private: 00411 00412 double &val; 00413 00414 public: 00415 00416 WvArgsDoubleOption(int _short_option, 00417 WvStringParm _long_option, 00418 WvStringParm _desc, 00419 WvStringParm _arg_desc, 00420 double &_val) 00421 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00422 val(_val) 00423 { 00424 } 00425 00426 virtual WvString process(WvStringParm arg) 00427 { 00428 char *tailptr = NULL; 00429 errno = 0; 00430 double tmp = strtod(arg, &tailptr); 00431 if (errno == ERANGE) 00432 { 00433 // Out of range 00434 return WvString("`%s': invalid number.", arg); 00435 } 00436 else if (*tailptr) 00437 { 00438 // Invalid number 00439 return WvString("`%s': invalid number.", arg); 00440 } 00441 else 00442 { 00443 val = tmp; 00444 return WvString::null; 00445 } 00446 } 00447 }; 00448 00449 00450 class WvArgsStringOption : public WvArgsArgOption 00451 { 00452 private: 00453 00454 WvString &val; 00455 00456 public: 00457 00458 WvArgsStringOption(int _short_option, 00459 WvStringParm _long_option, 00460 WvStringParm _desc, 00461 WvStringParm _arg_desc, 00462 WvString &_val) 00463 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00464 val(_val) 00465 { 00466 } 00467 00468 virtual WvString process(WvStringParm arg) 00469 { 00470 val = arg; 00471 return WvString::null; 00472 } 00473 }; 00474 00475 00476 class WvArgsStringListAppendOption : public WvArgsArgOption 00477 { 00478 private: 00479 00480 WvStringList &val; 00481 00482 public: 00483 00484 WvArgsStringListAppendOption(int _short_option, 00485 WvStringParm _long_option, 00486 WvStringParm _desc, 00487 WvStringParm _arg_desc, 00488 WvStringList &_val) 00489 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00490 val(_val) 00491 { 00492 } 00493 00494 virtual WvString process(WvStringParm arg) 00495 { 00496 val.append(arg); 00497 return WvString::null; 00498 } 00499 }; 00500 00501 00502 class WvArgsArgCallbackOption : public WvArgsArgOption 00503 { 00504 private: 00505 00506 WvArgs::ArgCallback cb; 00507 void *ud; 00508 00509 public: 00510 00511 WvArgsArgCallbackOption(int _short_option, 00512 WvStringParm _long_option, 00513 WvStringParm _desc, 00514 WvStringParm _arg_desc, 00515 WvArgs::ArgCallback _cb, 00516 void *_ud) 00517 : WvArgsArgOption(_short_option, _long_option, _desc, _arg_desc), 00518 cb(_cb), ud(_ud) 00519 { 00520 } 00521 00522 virtual WvString process(WvStringParm arg) 00523 { 00524 if (cb(arg, ud)) 00525 return WvString::null; 00526 else 00527 return WvString("invalid option: `%s'", arg); 00528 } 00529 }; 00530 00531 00532 WvArgsData::WvArgsData() 00533 : flags(0), argp_(NULL), argp_index(0), argp_size(0), 00534 required_args(0), maximum_args(0), last_no_key(-1) 00535 { 00536 } 00537 00538 00539 WvArgsData::~WvArgsData() 00540 { 00541 if (argp_) 00542 free(argp_); 00543 } 00544 00545 00546 argp_option *WvArgsData::argp() const 00547 { 00548 return argp_; 00549 } 00550 00551 00552 void *WvArgsData::self() const 00553 { 00554 return (void *)this; 00555 } 00556 00557 00558 void WvArgsData::add(WvArgsOption *option) 00559 { 00560 if (!option) 00561 return; 00562 00563 if (!option->short_option) 00564 option->short_option = last_no_key--; 00565 00566 options_list.append(option, true); 00567 options_dict.add(option, false); 00568 } 00569 00570 00571 // This method removes both short_option and long_option from the 00572 // options_* structures. Completely. 00573 void WvArgsData::remove(char short_option, WvStringParm long_option) 00574 { 00575 // First, look through options_list, and remove them from 00576 // options_dict once we find them. 00577 WvArgsOptionList::Iter i(options_list); 00578 for (i.rewind(); i.next(); ) 00579 { 00580 bool matches_short = false; 00581 bool matches_long = false; 00582 00583 if (short_option != '\0' && i->short_option == short_option) 00584 matches_short = true; 00585 if (!long_option.isnull() && i->long_option == long_option) 00586 matches_long = true; 00587 00588 if (matches_short && matches_long 00589 || matches_short && i->long_option.isnull() 00590 || matches_long && i->short_option == '\0') 00591 { 00592 // Delete this item from the data-structures 00593 options_dict.remove(i.ptr()); 00594 i.xunlink(); 00595 if (argp_) 00596 { 00597 free(argp_); 00598 argp_ = NULL; 00599 } 00600 } 00601 else if (matches_short) 00602 { 00603 // Update the short description and change how it's filed 00604 // in the dictionary. 00605 i->short_option = '\0'; 00606 options_dict.remove(i.ptr()); 00607 options_dict.add(i.ptr(), false); 00608 } 00609 else if (matches_long) 00610 { 00611 // Update the long description only 00612 i->long_option = WvString::null; 00613 } 00614 } 00615 } 00616 00617 00618 void WvArgsData::zap() 00619 { 00620 options_dict.zap(); 00621 options_list.zap(); 00622 00623 if (argp_) 00624 { 00625 free(argp_); 00626 argp_ = NULL; 00627 } 00628 } 00629 00630 00631 void WvArgsData::argp_init(size_t size) 00632 { 00633 argp_size = size; 00634 if (argp_size < 1) 00635 argp_size = 1; 00636 00637 // I'm sorry to use malloc(), but this argp is a C library 00638 argp_ = (argp_option *)malloc(argp_size * sizeof(argp_option)); 00639 // Terminate the empty array 00640 memset(argp_, 0, sizeof(argp_option)); 00641 } 00642 00643 00644 void WvArgsData::argp_build() 00645 { 00646 if (!argp_) 00647 argp_init(options_list.count() + 2); 00648 00649 WvArgsOptionList::Iter i(options_list); 00650 for (i.rewind(); i.next(); ) 00651 i->add_to_argp(*this); 00652 } 00653 00654 00655 bool WvArgsData::argp_add(const argp_option &option) 00656 { 00657 if (argp_index >= (argp_size - 1)) 00658 { 00659 if (!argp_double()) 00660 return false; 00661 } 00662 00663 // Make a copy of the option that we're building. 00664 memcpy(argp_ + argp_index, &option, sizeof(argp_option)); 00665 // Terminate the array. 00666 ++argp_index; 00667 memset(argp_ + argp_index, 0, sizeof(argp_option)); 00668 return true; 00669 } 00670 00671 00672 bool WvArgsData::argp_add(const char *name, int key, const char *arg, 00673 int flags, const char *doc, int group) 00674 { 00675 if (argp_index >= (argp_size - 1)) 00676 { 00677 if (!argp_double()) 00678 return false; 00679 } 00680 00681 // Set the elements. 00682 argp_option *option = argp_ + argp_index; 00683 option->name = name; 00684 option->key = key; 00685 option->arg = arg; 00686 option->flags = flags; 00687 option->doc = doc; 00688 option->group = group; 00689 // Terminate the array. 00690 ++argp_index; 00691 memset(argp_ + argp_index, 0, sizeof(argp_option)); 00692 return true; 00693 } 00694 00695 00696 bool WvArgsData::argp_double() 00697 { 00698 // We won't be able to fit the next entry into the array 00699 void *tmp = realloc(argp_, 2 * argp_size * sizeof(argp_option)); 00700 if (!tmp) 00701 return false; 00702 00703 argp_ = (argp_option *)tmp; 00704 argp_size *= 2; 00705 return true; 00706 } 00707 00708 00709 void WvArgsData::add_required_arg() 00710 { 00711 ++required_args; 00712 } 00713 00714 00715 void WvArgsData::subtract_required_arg() 00716 { 00717 --required_args; 00718 } 00719 00720 00721 const WvStringList &WvArgsData::args() const 00722 { 00723 return args_; 00724 } 00725 00726 00727 error_t WvArgsData::parser(int key, char *arg, struct argp_state *state) 00728 { 00729 WvArgsData *data = (WvArgsData *)state->input; 00730 00731 switch (key) 00732 { 00733 case ARGP_KEY_ARG: 00734 if (state->arg_num >= data->maximum_args) 00735 { 00736 // Too many arguments 00737 argp_usage(state); 00738 } 00739 data->args_.append(arg); 00740 break; 00741 00742 case ARGP_KEY_NO_ARGS: 00743 case ARGP_KEY_END: 00744 if (state->arg_num < data->required_args) 00745 { 00746 // Too few arguments 00747 argp_usage(state); 00748 } 00749 break; 00750 00751 default: 00752 WvArgsOption *option = data->options_dict[key]; 00753 if (option) 00754 { 00755 WvString error = option->process(arg); 00756 if (!error.isnull()) 00757 { 00758 argp_failure(state, argp_err_exit_status, 0, 00759 "%s", error.cstr()); 00760 return EINVAL; 00761 } 00762 } 00763 else 00764 return ARGP_ERR_UNKNOWN; 00765 } 00766 00767 return 0; 00768 } 00769 00770 00771 WvArgs::WvArgs() 00772 : data(new WvArgsData()) 00773 { 00774 } 00775 00776 00777 WvArgs::~WvArgs() 00778 { 00779 if (data) 00780 delete data; 00781 } 00782 00783 00784 bool WvArgs::process(int argc, char **argv, WvStringList *remaining_args) 00785 { 00786 if (!data->argp()) 00787 data->argp_build(); 00788 00789 // Setup --help headers and footers 00790 WvString prog_doc; 00791 if (header && footer) 00792 prog_doc = WvString("%s\v%s", header, footer); 00793 else if (header) 00794 prog_doc = WvString("%s", header); 00795 else if (footer) 00796 prog_doc = WvString(" \v%s", footer); 00797 00798 // Setup the constant version number and e-mail address 00799 argp_program_version = version; 00800 argp_program_bug_address = email; 00801 00802 struct argp argp = { data->argp(), &WvArgsData::parser, args_doc, prog_doc, 00803 0, 0, 0 }; 00804 00805 bool error = argp_parse(&argp, argc, argv, data->flags, 0, data->self()); 00806 00807 if (remaining_args) 00808 { 00809 remaining_args->zap(); 00810 WvStringList::Iter i(data->args()); 00811 for (i.rewind(); i.next(); ) 00812 remaining_args->add(new WvString(*i), true); 00813 } 00814 00815 return !error; 00816 } 00817 00818 00819 void WvArgs::set_version(WvStringParm version) 00820 { 00821 this->version = version; 00822 } 00823 00824 00825 void WvArgs::set_email(WvStringParm email) 00826 { 00827 this->email = email; 00828 } 00829 00830 00831 void WvArgs::set_help_header(WvStringParm header) 00832 { 00833 this->header = header; 00834 } 00835 00836 00837 void WvArgs::set_help_footer(WvStringParm footer) 00838 { 00839 this->footer = footer; 00840 } 00841 00842 00843 void WvArgs::print_usage(int argc, char **argv) 00844 { 00845 struct argp argp = { data->argp(), 0, 0, 0, 0, 0, 0 }; 00846 argp_help(&argp, stdout, ARGP_HELP_STD_USAGE, argv[0]); 00847 } 00848 00849 00850 void WvArgs::print_help(int argc, char **argv) 00851 { 00852 struct argp argp = { data->argp(), 0, 0, 0, 0, 0, 0 }; 00853 argp_help(&argp, stdout, ARGP_HELP_STD_HELP, argv[0]); 00854 } 00855 00856 void WvArgs::add_set_bool_option(char short_option, WvStringParm long_option, 00857 WvStringParm desc, bool &val) 00858 { 00859 data->remove(short_option, long_option); 00860 data->add(new WvArgsSetBoolOption(short_option, long_option, desc, val)); 00861 } 00862 00863 00864 void WvArgs::add_reset_bool_option(char short_option, WvStringParm long_option, 00865 WvStringParm desc, bool &val) 00866 { 00867 data->remove(short_option, long_option); 00868 data->add(new WvArgsResetBoolOption(short_option, long_option, desc, val)); 00869 } 00870 00871 00872 void WvArgs::add_flip_bool_option(char short_option, WvStringParm long_option, 00873 WvStringParm desc, bool &val) 00874 { 00875 data->remove(short_option, long_option); 00876 data->add(new WvArgsFlipBoolOption(short_option, long_option, desc, val)); 00877 } 00878 00879 00880 void WvArgs::add_option(char short_option, WvStringParm long_option, 00881 WvStringParm desc, NoArgCallback cb, void *ud) 00882 { 00883 data->remove(short_option, long_option); 00884 data->add(new WvArgsNoArgCallbackOption(short_option, long_option, desc, 00885 cb, ud)); 00886 } 00887 00888 void WvArgs::add_option(char short_option, WvStringParm long_option, 00889 WvStringParm desc, WvStringParm arg_desc, int &val) 00890 { 00891 data->remove(short_option, long_option); 00892 data->add(new WvArgsIntOption(short_option, long_option, desc, arg_desc, 00893 val)); 00894 } 00895 00896 void WvArgs::add_option(char short_option, WvStringParm long_option, 00897 WvStringParm desc, WvStringParm arg_desc, long &val) 00898 { 00899 data->remove(short_option, long_option); 00900 data->add(new WvArgsLongOption(short_option, long_option, desc, arg_desc, 00901 val)); 00902 } 00903 00904 void WvArgs::add_option(char short_option, WvStringParm long_option, 00905 WvStringParm desc, WvStringParm arg_desc, float &val) 00906 { 00907 data->remove(short_option, long_option); 00908 data->add(new WvArgsFloatOption(short_option, long_option, desc, arg_desc, 00909 val)); 00910 } 00911 00912 void WvArgs::add_option(char short_option, WvStringParm long_option, 00913 WvStringParm desc, WvStringParm arg_desc, double &val) 00914 { 00915 data->remove(short_option, long_option); 00916 data->add(new WvArgsDoubleOption(short_option, long_option, desc, 00917 arg_desc, val)); 00918 } 00919 00920 void WvArgs::add_option(char short_option, WvStringParm long_option, 00921 WvStringParm desc, WvStringParm arg_desc, 00922 WvString &val) 00923 { 00924 data->remove(short_option, long_option); 00925 data->add(new WvArgsStringOption(short_option, long_option, desc, 00926 arg_desc, val)); 00927 } 00928 00929 void WvArgs::add_option(char short_option, WvStringParm long_option, 00930 WvStringParm desc, WvStringParm arg_desc, 00931 WvStringList &val) 00932 { 00933 data->remove(short_option, long_option); 00934 data->add(new WvArgsStringListAppendOption(short_option, long_option, 00935 desc, arg_desc, val)); 00936 } 00937 00938 void WvArgs::add_option(char short_option, WvStringParm long_option, 00939 WvStringParm desc, WvStringParm arg_desc, 00940 ArgCallback cb, void *ud) 00941 { 00942 data->remove(short_option, long_option); 00943 data->add(new WvArgsArgCallbackOption(short_option, long_option, desc, 00944 arg_desc, cb, ud)); 00945 } 00946 00947 00948 void WvArgs::remove_option(char short_option) 00949 { 00950 data->remove(short_option, WvString::null); 00951 } 00952 00953 00954 void WvArgs::remove_option(WvStringParm long_option) 00955 { 00956 data->remove(0, long_option); 00957 } 00958 00959 00960 void WvArgs::remove_all_options() 00961 { 00962 data->zap(); 00963 } 00964 00965 00966 void WvArgs::add_required_arg(WvStringParm desc, bool multiple) 00967 { 00968 data->add_required_arg(); 00969 if (!!args_doc) 00970 args_doc.append(" "); 00971 args_doc.append(desc); 00972 if (multiple) 00973 { 00974 args_doc.append("..."); 00975 data->maximum_args = LONG_MAX; 00976 } 00977 else if (data->maximum_args < LONG_MAX) 00978 ++(data->maximum_args); 00979 } 00980 00981 00982 void WvArgs::add_optional_arg(WvStringParm desc, bool multiple) 00983 { 00984 // an optional arg is a required arg without the requirement :-) 00985 add_required_arg(WvString("[%s]", desc), multiple); 00986 data->subtract_required_arg(); 00987 } 00988 00989 00990 bool WvArgs::get_flag(const flags_t flag) const 00991 { 00992 switch (flag) 00993 { 00994 case NO_EXIT_ON_ERRORS: 00995 return data->flags & ARGP_NO_EXIT; 00996 default: 00997 return false; 00998 } 00999 } 01000 01001 01002 void WvArgs::set_flag(const flags_t flag, const bool value) 01003 { 01004 printf("set_flag(%d, %d)\n", flag, value); 01005 unsigned int mask; 01006 switch (flag) 01007 { 01008 case NO_EXIT_ON_ERRORS: 01009 mask = ARGP_NO_EXIT; 01010 break; 01011 default: 01012 return; 01013 } 01014 01015 if (value) 01016 data->flags |= mask; 01017 else 01018 data->flags &= ~mask; 01019 01020 printf("set_flag(%d, %d) = %d\n", flag, value, data->flags); 01021 }