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