wvargs.cc

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 #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;          // Last element in the options array
00081     size_t argp_size;           // Size of the options array
00082 
00083     // I create two data-structures, only one of them actually owning
00084     // the objects, of course.  The List is for ordered construction
00085     // of argp_.  The Dict is for constant-time lookups when
00086     // process()ing options.
00087     WvArgsOptionList options_list; // An ordered list of WvArgsOptions
00088     WvArgsOptionDict options_dict; // A constant-time lookup of them
00089 
00090     WvStringList args_;         // Arguments after all options have been parsed
00091     size_t required_args;       // Number of these mandatory arguments.
00092     size_t maximum_args;        // Number of maximum arguments.
00093 
00094     int last_no_key;            // Last key for options with no short_option
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             // Out of range
00299             return WvString("`%s': invalid number.", arg);
00300         }
00301         else if (*tailptr)
00302         {
00303             // Invalid number
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             // Out of range
00341             return WvString("`%s': invalid number.", arg);
00342         }
00343         else if (*tailptr)
00344         {
00345             // Invalid number
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             // Out of range
00383             return WvString("`%s': invalid number.", arg);
00384         }
00385         else if (*tailptr)
00386         {
00387             // Invalid number
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             // Out of range
00425             return WvString("`%s': invalid number.", arg);
00426         }
00427         else if (*tailptr)
00428         {
00429             // Invalid number
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 // This method removes both short_option and long_option from the
00563 // options_* structures.  Completely.
00564 void WvArgsData::remove(char short_option, WvStringParm long_option)
00565 {
00566     // First, look through options_list, and remove them from
00567     // options_dict once we find them.
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             // Delete this item from the data-structures
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             // Update the short description and change how it's filed
00595             // in the dictionary.
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             // Update the long description only
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     // I'm sorry to use malloc(), but this argp is a C library
00629     argp_ = (argp_option *)malloc(argp_size * sizeof(argp_option));
00630     // Terminate the empty array
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     // Make a copy of the option that we're building.
00655     memcpy(argp_ + argp_index, &option, sizeof(argp_option));
00656     // Terminate the array.
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     // Set the elements.
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     // Terminate the array.
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     // We won't be able to fit the next entry into the array
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             // Too many arguments
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             // Too few arguments
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     // Setup --help headers and footers
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     // Setup the constant version number and e-mail address
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     // an optional arg is a required arg without the requirement :-)
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 }

Generated on Mon Feb 5 10:54:28 2007 for WvStreams by  doxygen 1.5.1