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

Generated on Thu Jan 24 16:50:55 2008 for WvStreams by  doxygen 1.5.4