core/vul/vul_arg.cxx
Go to the documentation of this file.
00001 // This is core/vul/vul_arg.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // Note that even though this file defines instances of a templated
00008 // class, it is a .cxx file and not a .txx file because it does not
00009 // supply a class definition for use by clients.
00010 //
00011 // If you need to define your own vul_arg<T>, you should #include vul_arg.h
00012 // ONLY, in your source file (myarg.cxx, say), define these three global
00013 // functions (which can by static if you like) in myarg.cxx
00014 // \code
00015 //   void settype(vul_arg<T> &);
00016 //   void print_value(vul_arg<T> const &, vcl_ostream &);
00017 //   int  parse(vul_arg<T>*, char**);
00018 // \endcode
00019 // and then instantiate the class vul_arg<T> as usual (in myarg.cxx).
00020 
00021 #include "vul_arg.h"
00022 
00023 #include <vcl_cassert.h>
00024 #include <vcl_algorithm.h>
00025 #include <vcl_iostream.h>
00026 #include <vcl_sstream.h>
00027 #include <vcl_cstring.h>
00028 #include <vcl_cstdlib.h> // exit()
00029 #include <vcl_cmath.h>   // floor()
00030 #include <vcl_vector.h>
00031 #include <vcl_list.h>
00032 
00033 #include <vul/vul_sprintf.h>
00034 #include <vul/vul_string.h>
00035 #include <vul/vul_reg_exp.h>
00036 #include <vul/vul_printf.h>
00037 
00038 //------------------------------------------------------------------------------
00039 
00040 char const* vul_arg_base::option()
00041 { return option_.c_str(); }
00042 
00043 char const* vul_arg_base::help()
00044 { return help_.c_str(); }
00045 
00046 //: Parse the list of arguments....
00047 void vul_arg_parse(int& argc, char **& argv,
00048                    bool warn_about_unrecognized_arguments)
00049 {
00050   vul_arg_base::parse_deprecated(argc, argv,
00051                                  warn_about_unrecognized_arguments);
00052 }
00053 
00054 //: Add an externally supplied list of args to the global list.
00055 void vul_arg_include(vul_arg_info_list& l)
00056 {
00057   vul_arg_base::include_deprecated(l);
00058 }
00059 
00060 //: Print all args, and usage messages.
00061 void vul_arg_display_usage_and_exit(char const* msg)
00062 {
00063   vul_arg_base::display_usage_and_exit(msg);
00064 }
00065 
00066 
00067 //: Returns true if arg was set on the command line.
00068 bool vul_arg_base::set() const
00069 { return set_; }
00070 
00071 static vul_arg_info_list& current_list() // instance "method"
00072 {
00073   static vul_arg_info_list list;
00074   return list;
00075 }
00076 
00077 //: Add another vul_arg_info_list to the current one.
00078 // This allows for the inclusion of different sets of arguments into the
00079 // main program, from different libraries.
00080 void vul_arg_base::include_deprecated(vul_arg_info_list& l)
00081 {
00082   current_list().include(l);
00083 }
00084 
00085 //
00086 void vul_arg_base::add_to_current(vul_arg_base* a)
00087 {
00088   current_list().add(a);
00089 }
00090 
00091 //: The main static method.
00092 void vul_arg_base::parse_deprecated(int& argc, char **& argv, bool warn_about_unrecognized_arguments)
00093 {
00094   current_list().parse(argc, argv, warn_about_unrecognized_arguments);
00095 }
00096 
00097 void vul_arg_base::set_help_option(char const* str)
00098 {
00099   current_list().set_help_option( str);
00100 }
00101 
00102 void vul_arg_base::set_help_precis(char const* str)
00103 {
00104   current_list().set_help_precis( str);
00105 }
00106 
00107 void vul_arg_base::set_help_description(char const* str)
00108 {
00109   current_list().set_help_description( str);
00110 }
00111 
00112 void vul_arg_base::display_usage(char const* msg)
00113 {
00114   if (msg) vcl_cerr << "** WARNING ** " << msg << vcl_endl;
00115   current_list().display_help("");
00116 }
00117 
00118 void vul_arg_base::display_usage_and_exit(char const* msg)
00119 {
00120   if (msg) vcl_cerr << "** ERROR ** " << msg << vcl_endl;
00121   current_list().display_help("");
00122   vcl_exit(-1);
00123 }
00124 
00125 // vul_arg_base constructors
00126 
00127 vul_arg_base::vul_arg_base(vul_arg_info_list& l, char const* option_string, char const* helpstring)
00128 : set_(false),
00129   option_(option_string?option_string:"\0"),
00130   help_(helpstring?helpstring:"\0")
00131 {
00132   l.add(this);
00133 }
00134 
00135 vul_arg_base::vul_arg_base(char const* option_string, char const* helpstring)
00136 : set_(false),
00137   option_(option_string?option_string:"\0"),
00138   help_(helpstring?helpstring:"\0")
00139 {
00140   current_list().add(this);
00141 }
00142 
00143 //------------------------------------------------------------------------------
00144 
00145 //: Change the help operator (defaults to -?)
00146 void vul_arg_info_list::set_help_option(char const* str)
00147 {
00148   // check that the operator isn't already being used
00149   for (unsigned int i=0; i<args_.size(); i++) {
00150     if (vcl_strcmp(args_[i]->option(),str) == 0) {
00151       vcl_cerr << "vul_arg_info_list: WARNING: requested help operator already assigned\n";
00152       return;
00153     }
00154   }
00155 
00156   help_ = str;
00157 }
00158 
00159 
00160 //: Add an argument to the list.
00161 void vul_arg_info_list::add(vul_arg_base* argmt)
00162 {
00163   if ( argmt->option() && help_ == argmt->option() )
00164     vcl_cerr << "vul_arg_info_list: WARNING: '-" << help_
00165              << "' option reserved and will be ignored\n";
00166   else
00167     args_.push_back(argmt);
00168 }
00169 
00170 //: Append another list.  The other list is not copied, just pointed to.
00171 void vul_arg_info_list::include(vul_arg_info_list& l)
00172 {
00173   assert(&l != this);
00174 
00175   for (unsigned int i = 0; i < l.args_.size(); ++i)
00176     add(l.args_[i]);
00177 }
00178 
00179 //: Display help about each option in the arg list.
00180 // Note that this function does not exit at the end.
00181 void vul_arg_info_list::display_help( char const*progname)
00182 {
00183   if (progname)
00184     vcl_cerr << "Usage: " << progname << ' ';
00185   else
00186     vcl_cerr << "Usage: aprog ";
00187 
00188   // Print "prog [-a int] string string"
00189   for (unsigned int i=0; i< args_.size(); i++) {
00190     if (args_[i]->option()) {
00191       vcl_cerr << '[' << args_[i]->option();
00192       if (vcl_strlen(args_[i]->type_)> 0)
00193         vcl_cerr << ' ' << args_[i]->type_;
00194       vcl_cerr << "] ";
00195     } else {
00196       // options without switches are required.
00197       vcl_cerr << args_[i]->type_ << ' ';
00198     }
00199   }
00200 
00201   vcl_cerr << vcl_endl << command_precis_ << vcl_endl;
00202 
00203   // Find longest option, type name, or default
00204   vcl_size_t maxl_option  = vcl_max(vcl_size_t(8), help_.size()); // Length of "REQUIRED" or help option
00205   vcl_size_t maxl_type = 4; // Length of "Type", minimum "bool"
00206   //  int maxl_default = 0;
00207   for (unsigned int i=0; i< args_.size(); i++)
00208     if (!args_[i]->help_.empty()) {
00209       if (!args_[i]->option_.empty()) {
00210         vcl_size_t l = vcl_strlen(args_[i]->option());
00211         if (l > maxl_option) maxl_option = l;
00212       }
00213       vcl_size_t l = vcl_strlen(args_[i]->type_);
00214       if (l > maxl_type) maxl_type = l;
00215     }
00216 
00217   // Print long form of args
00218   vcl_string fmtbuf = vul_sprintf("%%%ds %%-%ds %%s ", maxl_option, maxl_type);
00219 
00220   // Do required args first
00221   vul_printf(vcl_cerr, "REQUIRED:\n");
00222   for (unsigned int i=0; i< args_.size(); i++)
00223     if (!args_[i]->help_.empty())
00224       if (args_[i]->option_.empty()) {
00225         vul_printf(vcl_cerr, fmtbuf.c_str(), "", args_[i]->type_, args_[i]->help_.c_str());
00226         vcl_cerr << " ["; args_[i]->print_value(vcl_cerr); vcl_cerr << "]\n"; // default
00227       }
00228   vcl_cerr << vcl_endl;
00229 
00230   // Then others
00231   vul_printf(vcl_cerr, "Optional:\n");
00232   vul_printf(vcl_cerr, fmtbuf.c_str(), "Switch", "Type", "Help [default value]") << vcl_endl << vcl_endl;
00233   for (unsigned int i=0; i< args_.size(); i++)
00234     if (!args_[i]->help_.empty())
00235       if (!args_[i]->option_.empty()) {
00236         vul_printf(vcl_cerr, fmtbuf.c_str(), args_[i]->option(), args_[i]->type_, args_[i]->help_.c_str());
00237         vcl_cerr << " ["; args_[i]->print_value(vcl_cerr); vcl_cerr << "]\n"; // default
00238       }
00239   vul_printf(vcl_cerr, fmtbuf.c_str(), help_.c_str(), "bool", "Print this message\n");
00240 
00241   if (!description_.empty()) vcl_cerr << '\n' << description_;
00242 }
00243 
00244 //: Parse the command line, using the current list of args.
00245 //  Remove all recognised arguments from the command line by modifying argc and argv.
00246 void vul_arg_info_list::parse(int& argc, char **& argv, bool warn_about_unrecognized_arguments)
00247 {
00248   vcl_vector<bool> done_once(args_.size(), false);
00249 
00250   // 0. Check that there are no duplicate switches, O(n^2) as n is tiny.
00251   for (unsigned int i = 0; i < args_.size(); ++i)
00252     if (!args_[i]->option_.empty())
00253       for (unsigned int j = i+1; j < args_.size(); ++j)
00254         if (args_[i]->option_ == args_[j]->option_)
00255           vcl_cerr << "vul_arg_info_list: WARNING: repeated switch ["
00256                    << args_[j]->option_ << "]\n";
00257 
00258   // 0a. Clear "set" flags on args
00259   for (unsigned int i = 0; i < args_.size(); ++i)
00260     args_[i]->set_ = false;
00261 
00262   // Generate shorter command name
00263   char * cmdname = argv[0]+vcl_strlen(argv[0]);
00264   while (cmdname > argv[0] && *cmdname != '/' && *cmdname != '\\') --cmdname ;
00265   if (*cmdname == '\\' || *cmdname == '/') cmdname++;
00266 
00267 
00268   // 1. Collect option arguments (i.e. ones with "-"),
00269   // and squeeze them out of argv.
00270   // Make sure to do things sequentially
00271 
00272   char ** my_argv = argv + 1; // Skip program name
00273   while (*my_argv) {
00274     char* argmt = *my_argv;
00275     bool eaten = false;
00276     for (unsigned int i = 0; i < args_.size(); ++i) {
00277       if (!args_[i]->option_.empty()) {
00278         if ( help_ == argmt ) { // look for the '-?' operator (i.e. HELP)
00279           display_help(cmdname);
00280           vcl_exit(1);
00281         }
00282 
00283         if (args_[i]->option_==argmt) {
00284           done_once[i] = true;
00285           int advance = args_[i]->parse(my_argv + 1);
00286           args_[i]->set_ = true;
00287           if (advance >= 0) {
00288             // Pull down remaining args
00289             for (char ** av = my_argv; *(av + advance); ++av)
00290               *av = *(av + advance + 1);
00291 
00292             eaten = true;
00293             break;
00294           }
00295         }
00296       }
00297     }
00298     if (!eaten)
00299       ++my_argv;
00300   }
00301 
00302   if (verbose_) {
00303     vcl_cerr << "args remaining:";
00304     for (char ** av = argv; *av; ++av)
00305       vcl_cerr << " [" << *av << ']';
00306     vcl_cerr << vcl_endl;
00307   }
00308 
00309 
00310   // 2. Just take from the list to fill the non-option arguments
00311   my_argv = argv + 1;
00312   int num_satisfied = 0;
00313   for (unsigned int i = 0; i < args_.size(); ++i)
00314     if (args_[i]->option_.empty()) {
00315       if (*my_argv) {
00316         done_once[i] = true;
00317         int advance = args_[i]->parse(my_argv);
00318         args_[i]->set_ = true;
00319         my_argv += advance;
00320         ++num_satisfied;
00321       } else {
00322         display_help(cmdname);
00323 
00324         vcl_cerr << "\nargParse::ERROR: Required arg " << (num_satisfied+1)
00325                  << " not supplied\n\n";
00326         vcl_exit(1);
00327       }
00328     }
00329 
00330 
00331   // 3. Move my_argv down to first unused arg, and reset argc
00332   argc = 1;
00333   for (char ** av = my_argv; *av; ++av)
00334     ++argc;
00335   for (int i = 1; i < argc; ++i)
00336     argv[i] = my_argv[i-1];
00337   argv[argc] = 0;
00338 
00339   // 4. Error checking.
00340   //
00341   // 4.2 Sometimes it's bad if all args weren't used (i.e. trailing args)
00342   if (autonomy_ == all) {
00343     vcl_cerr << "vul_arg_info_list: Some arguments were unused: ";
00344     for (char ** av = argv; *av; ++av)
00345       vcl_cerr << ' ' << *av;
00346     vcl_cerr << vcl_endl;
00347     display_help(cmdname);
00348   }
00349 
00350   // 4.3 It's often bad if a switch was not recognized.
00351   if (warn_about_unrecognized_arguments)
00352     for (char ** av = argv; *av; ++av)
00353       if (**av == '-') {
00354         display_help(cmdname);
00355         vcl_cerr << "vul_arg_info_list: WARNING: Unparsed switch [" << *av << "]\n";
00356       }
00357 
00358   // 5. Some people like a chatty program.
00359 #ifdef DEBUG //fsm: do not print outcome - it looks like an error message.
00360   if (verbose_) {
00361     // Print outcome
00362     for (unsigned int i = 0; i < args_.size(); ++i)
00363       if (args[i]->option_) {
00364         vcl_cerr << "Switch " << args_[i]->option_ << ": "
00365                  << (!done_once[i] ? "not " : "") << "done, value [";
00366         args[i]->print_value(vcl_cerr);
00367         vcl_cerr << "]\n";
00368       }
00369 
00370     for (unsigned int i = 0; i < args.size(); ++i)
00371       if (!args[i]->option_) {
00372         vcl_cerr << "Trailer: ";
00373         args_[i]->print_value(vcl_cerr);
00374         vcl_cerr << vcl_endl;
00375       }
00376 
00377     vcl_cerr << "args remaining [argc = " << argc << "]:";
00378     for (char ** av = argv; *av; ++av)
00379       vcl_cerr << ' ' << *av;
00380     vcl_cerr << "\n--------------\n";
00381   }
00382 #endif
00383 }
00384 
00385 
00386 //------------------------------------------------------------------------------
00387 
00388 //: function to parse matlab or UNIX style integer ranges.
00389 // eg. 1:3 is matlab for 1,2,3 and 1-3 is UNIX for 1,2,3
00390 //
00391 // parsed as follows:
00392 //   any character other than '-' and ':' is considered a list separator
00393 //   simple ranges can be written as 1:3 or 1-3 (=1,2,3) or 3:1 (=3,2,1)
00394 //   complete ranges can be written as 1:2:5 or 1-2-5 (=1,3,5)
00395 //   negative numbers are handled 'transparently'
00396 //   (e.g. -1:-3 or -1--3 or even -1--1--3 ...:).
00397 //
00398 // Returns 1 on success and 0 on failure.
00399 //
00400 static int list_parse(vcl_list<int> &out, char ** argv)
00401 {
00402   out.clear();
00403 
00404   // Empty list specified as the last argument.
00405   if ( !argv[0] ) return 0; // failure
00406 
00407   vcl_string str(argv[0]);
00408 
00409 #define REGEXP_INTEGER "\\-?[0123456789]+"
00410 
00411   vul_reg_exp range_regexp("(" REGEXP_INTEGER ")"      // int
00412                            "([:-]" REGEXP_INTEGER ")?" // :int [optional]
00413                            "([:-]" REGEXP_INTEGER ")?" // :int [optional]
00414                           );
00415 
00416   while (str.length() > 0 && range_regexp.find(str)) {
00417     // the start/end positions (ref from 0) of the
00418     //    current ',' separated token.
00419     vcl_ptrdiff_t start= range_regexp.start(0);
00420     vcl_ptrdiff_t endp = range_regexp.end(0);
00421     if (start != 0) {
00422       vcl_cerr << "vul_arg<vcl_list<int> >: Bad argument [" << argv[0] << "]\n";
00423       return 0; // failure
00424     }
00425 
00426 #ifdef DEBUG
00427     // this is the current token.
00428     vcl_string token = str.substr(start, endp);
00429     vcl_cerr << "token = " << token << '\n';
00430 #endif
00431     vcl_string match1 = range_regexp.match(1);
00432 #ifdef DEBUG
00433     vcl_cerr << "match1 = " << match1 << '\n';
00434 #endif
00435     vcl_string match2 = range_regexp.match(2);
00436 #ifdef DEBUG
00437     vcl_cerr << "match2 = " << match2 << '\n';
00438 #endif
00439     vcl_string match3 = range_regexp.match(3);
00440 #ifdef DEBUG
00441     vcl_cerr << "match3 = " << match3 << '\n';
00442 #endif
00443 
00444     // Remove this match from the front of string.
00445     str.erase(0, endp);
00446     if (str[0] == ',') str.erase(0, 1);
00447 
00448 #if 0
00449     vcl_cerr << "Range regexp matched [" << token <<  "]: parts ["
00450              << match1<<"] ["<<match2<<"] ["<<match3<<"]\n"
00451              << "  str->[" << str << "]\n";
00452 #endif
00453 
00454     bool matched2 = range_regexp.match(2).size() > 0;
00455     bool matched3 = range_regexp.match(3).size() > 0;
00456 
00457     int s = vul_string_atoi(match1);
00458     int d = 1;
00459     int e = s;
00460     if (matched3) {
00461       // "1:2:10"
00462       d = vul_string_atoi(match2.substr(1));
00463       e = vul_string_atoi(match3.substr(1));
00464     }
00465     else if (matched2)
00466       e = vul_string_atoi(match2.substr(1));
00467 
00468 #ifdef DEBUG
00469     vcl_cerr << "  " << s << ':' << d << ':' << e << '\n';
00470 #endif
00471     if (e >= s) {
00472       if (d < 0) {
00473         vcl_cerr << "WARNING: d < 0\n";
00474         d = -d;
00475       }
00476       for (int i = s; i <= e; i += d)
00477         out.push_back(i);
00478     } else {
00479       if (d > 0) {
00480         vcl_cerr << "WARNING: d > 0\n";
00481         d = -d;
00482       }
00483       for (int i = s; i >= e; i += d)
00484         out.push_back(i);
00485     }
00486   }
00487 
00488   if (str.empty())
00489     return 1; // success
00490 
00491   vcl_cerr << "vul_arg<vcl_list<int> >: Bad argument fragment  [" << str << "]\n";
00492   return 0;
00493 }
00494 
00495 //------------------------------------------------------------------------------
00496 
00497 // specializations for specific types.
00498 // In emacs, C-s for "//: unsigned" to find the implementation for vul_arg<unsigned>
00499 // In vi: "/^\/\/: unsigned"
00500 
00501 #if 1
00502 # define VDS VCL_DEFINE_SPECIALIZATION
00503 #else
00504 # define VDS /* template <> */
00505 #endif
00506 
00507 //: bool
00508 VDS void settype(vul_arg<bool> &argmt) { argmt.type_ = "bool"; }
00509 
00510 VDS void print_value(vcl_ostream &s, vul_arg<bool> const &argmt)
00511 { s << (argmt() ? "set" : "not set"); }
00512 
00513 VDS int parse(vul_arg<bool>* argmt, char ** /*argv*/)
00514 {
00515   argmt->value_ = true;
00516   return 0; // bool sucks zero args, most others take one.
00517 }
00518 
00519 template class vul_arg<bool>;
00520 
00521 //: int
00522 VDS void settype(vul_arg<int> &argmt) { argmt.type_ = "integer"; }
00523 
00524 VDS void print_value(vcl_ostream  &s, vul_arg<int> const &argmt)
00525 { s << argmt(); }
00526 
00527 VDS int parse(vul_arg<int>* argmt, char ** argv)
00528 {
00529   if ( !argv ||  !argv[0] ) {
00530     // no input
00531     vcl_cerr << "vul_arg_parse: Expected integer, none is provided.\n";
00532     return -1;
00533   }
00534 
00535   char* endptr = 0;
00536   double v = vcl_strtod(argv[0], &endptr);
00537   if (*endptr != '\0') {
00538     // There is junk after the number, or no number was found
00539     vcl_cerr << "vul_arg_parse: WARNING: Attempt to parse \"" << *argv << "\" as int\n";
00540     return -1;
00541   }
00542   if (v != vcl_floor(v)) {
00543     vcl_cerr << "vul_arg_parse: Expected integer: saw " << argv[0] << vcl_endl;
00544     return -1;
00545   }
00546   argmt->value_ = int(v);
00547   return 1;
00548 }
00549 
00550 template class vul_arg<int>;
00551 
00552 //: int64
00553 #if VXL_HAS_INT_64
00554 VDS void settype(vul_arg<vxl_int_64> &argmt) { argmt.type_ = "integer64"; }
00555 
00556 VDS void print_value(vcl_ostream  &s, vul_arg<vxl_int_64> const &argmt)
00557 { s << argmt(); }
00558 
00559 VDS int parse(vul_arg<vxl_int_64>* argmt, char ** argv)
00560 {
00561   if ( !argv ||  !argv[0] )
00562   {
00563     // no input
00564     vcl_cerr << "vul_arg_parse: Expected integer, none is provided.\n";
00565     return -1;
00566   }
00567 
00568   // Ensure only digits are present allowing for the special case of an l or L suffix
00569   int len = vcl_strlen(argv[0]);
00570   for (int i=0; i<len; ++i)
00571   {
00572     char tmp = argv[0][i];
00573     if (tmp < '0' || tmp > '9' || // Make sure the number only contains valid digits
00574         ((tmp == 'l' || tmp == 'L') && i != len-1) || // Or the trailing l or L suffix
00575         (tmp=='-' && i != 0 && len <= 2)) // Or a leading minus sign
00576     {
00577       vcl_cerr << "vul_arg_parse: WARNING: Attempt to parse \"" << *argv << "\" as int64\n";
00578       return -1;
00579     }
00580   }
00581 
00582   vcl_stringstream ss;
00583   ss << argv[0];
00584   ss >> argmt->value_;
00585 
00586   return 1;
00587 }
00588 
00589 template class vul_arg<vxl_int_64>;
00590 #endif
00591 
00592 //: unsigned
00593 VDS void settype(vul_arg<unsigned> &argmt) { argmt.type_ = "integer"; }
00594 
00595 VDS void print_value(vcl_ostream &s, vul_arg<unsigned> const &argmt)
00596 { s << argmt(); }
00597 
00598 VDS int parse(vul_arg<unsigned>* argmt, char ** argv)
00599 {
00600   if ( !argv ||  !argv[0] ) {
00601     // no input
00602     vcl_cerr << "vul_arg_parse: Expected integer, none is provided.\n";
00603     return -1;
00604   }
00605 
00606   char* endptr = 0;
00607   double v = vcl_strtod(argv[0], &endptr);
00608   if (*endptr != '\0') {
00609     // There is junk after the number, or no number was found
00610     vcl_cerr << "vul_arg_parse: WARNING: Attempt to parse " << *argv << " as int\n";
00611     return -1;
00612   }
00613   if (v != vcl_floor(v)) {
00614     vcl_cerr << "vul_arg_parse: Expected integer: saw " << argv[0] << vcl_endl;
00615     return -1;
00616   }
00617   argmt->value_ = unsigned(v);
00618   return 1;
00619 }
00620 
00621 template class vul_arg<unsigned>;
00622 
00623 //: float
00624 VDS void settype(vul_arg<float> &argmt) { argmt.type_ = "float"; }
00625 
00626 VDS void print_value(vcl_ostream &s, vul_arg<float> const &argmt)
00627 { s << argmt(); }
00628 
00629 VDS int parse(vul_arg<float>* argmt, char ** argv)
00630 {
00631   if ( !argv ||  !argv[0] ) {
00632     // no input
00633     vcl_cerr << "vul_arg_parse: Expected floating number, none is provided.\n";
00634     return -1;
00635   }
00636 
00637   char* endptr = 0;
00638   argmt->value_ = (float)vcl_strtod(argv[0], &endptr);
00639   if (*endptr == '\0')
00640     return 1;
00641   // There is junk after the number, or no number was found
00642   vcl_cerr << "vul_arg_parse: WARNING: Attempt to parse " << *argv << " as float\n";
00643   return -1;
00644 }
00645 
00646 template class vul_arg<float>;
00647 
00648 //: double
00649 VDS void settype(vul_arg<double> &argmt) { argmt.type_ = "float"; }
00650 
00651 VDS void print_value(vcl_ostream &s, vul_arg<double> const &argmt)
00652 { s << argmt(); }
00653 
00654 VDS int parse(vul_arg<double>* argmt, char ** argv)
00655 {
00656   if ( !argv ||  !argv[0] ) {
00657     // no input
00658     vcl_cerr << "vul_arg_parse: Expected floating number, none is provided.\n";
00659     return -1;
00660   }
00661 
00662   char* endptr = 0;
00663   argmt->value_ = vcl_strtod(argv[0], &endptr);
00664   if (*endptr == '\0')
00665     return 1;
00666   // There is junk after the number, or no number was found
00667   vcl_cerr << "vul_arg_parse: WARNING: Attempt to parse " << *argv << " as double\n";
00668   return -1;
00669 }
00670 
00671 template class vul_arg<double>;
00672 
00673 //: char *
00674 VDS void settype(vul_arg<char *> &argmt) { argmt.type_ = "string"; }
00675 
00676 VDS void print_value(vcl_ostream &s, vul_arg<char *> const &argmt)
00677 { s << '\'' << (argmt()?argmt():"(null)") << '\''; }
00678 
00679 VDS int parse(vul_arg<char*>* argmt, char ** argv)
00680 {
00681   argmt->value_ = argv[0]; // argv is valid till the end of the program so
00682   return 1;                // it's ok to just grab the pointer.
00683 }
00684 
00685 template class vul_arg<char*>;
00686 
00687 //: char const *
00688 VDS void settype(vul_arg<char const *> &argmt) { argmt.type_ = "string"; }
00689 
00690 VDS void print_value(vcl_ostream &s, vul_arg<char const *> const &argmt)
00691 { s << '\'' << (argmt()?argmt():"(null)") << '\''; }
00692 
00693 VDS int parse(vul_arg<char const *>* argmt, char ** argv)
00694 {
00695   if ( !argv ||  !argv[0] ) {
00696     // no input
00697     vcl_cerr << "vul_arg_parse: Expected string, none is provided.\n";
00698     return -1;
00699   }
00700 
00701   argmt->value_ = argv[0]; // argv is valid till the end of the program so
00702   return 1;                // it's ok to just grab the pointer.
00703 }
00704 
00705 template class vul_arg<char const*>;
00706 
00707 //: vcl_string
00708 VDS void settype(vul_arg<vcl_string> &argmt) { argmt.type_ = "string"; }
00709 
00710 VDS void print_value(vcl_ostream &s, vul_arg<vcl_string> const &argmt)
00711 { s << '\'' << argmt() << '\''; }
00712 
00713 VDS int parse(vul_arg<vcl_string>* argmt, char ** argv)
00714 {
00715   if ( !argv ||  !argv[0] ) {
00716     // no input
00717     vcl_cerr << "vul_arg_parse: Expected string, none is provided.\n";
00718     return -1;
00719   }
00720 
00721   if (argv[0]) {
00722     argmt->value_ = argv[0];
00723     return 1;
00724   }
00725   else {
00726     vcl_cerr << __FILE__ ": no argument to string option\n";
00727     return 0;
00728   }
00729 }
00730 
00731 template class vul_arg<vcl_string>;
00732 
00733 //: vcl_list<int>
00734 VDS void settype(vul_arg<vcl_list<int> > &argmt) { argmt.type_ = "integer list"; }
00735 
00736 VDS void print_value(vcl_ostream &s, vul_arg<vcl_list<int> > const &argmt)
00737 {
00738   for (vcl_list<int>::const_iterator i=argmt().begin(); i!=argmt().end(); ++i)
00739     s << ' ' << *i;
00740 }
00741 
00742 VDS int parse(vul_arg<vcl_list<int> >* argmt, char ** argv)
00743 {
00744   return list_parse(argmt->value_,argv);
00745 }
00746 
00747 template class vul_arg<vcl_list<int> >;
00748 
00749 //: vcl_vector<int>
00750 VDS void settype(vul_arg<vcl_vector<int> > &argmt) { argmt.type_ = "integer list"; }
00751 
00752 VDS void print_value(vcl_ostream &s, vul_arg<vcl_vector<int> > const &argmt)
00753 {
00754   for (unsigned int i=0; i<argmt().size(); ++i)
00755     s << ' ' << argmt()[i];
00756 }
00757 
00758 VDS int parse(vul_arg<vcl_vector<int> >* argmt, char ** argv)
00759 {
00760   vcl_list<int> tmp;
00761   int retval = list_parse(tmp,argv);
00762   // Defaults should be cleared when the user supplies a value
00763   argmt->value_.clear();
00764   for (vcl_list<int>::iterator i=tmp.begin(); i!=tmp.end(); ++i)
00765     argmt->value_.push_back( *i );
00766   return retval;
00767 }
00768 
00769 template class vul_arg<vcl_vector<int> >;
00770 
00771 //: vcl_vector<unsigned>
00772 VDS void settype(vul_arg<vcl_vector<unsigned> > &argmt) { argmt.type_="integer list"; }
00773 
00774 VDS void print_value(vcl_ostream &s, vul_arg<vcl_vector<unsigned> > const &argmt)
00775 {
00776   for (unsigned int i=0; i<argmt().size(); ++i)
00777     s << ' ' << argmt()[i];
00778 }
00779 
00780 VDS int parse(vul_arg<vcl_vector<unsigned> >* argmt, char ** argv)
00781 {
00782   vcl_list<int> tmp;
00783   int retval = list_parse(tmp,argv);
00784   // Defaults should be cleared when the user supplies a value
00785   argmt->value_.clear();
00786   for (vcl_list<int>::iterator i=tmp.begin(); i!=tmp.end(); ++i)
00787     argmt->value_.push_back( unsigned(*i) );
00788   return retval;
00789 }
00790 
00791 template class vul_arg<vcl_vector<unsigned> >;
00792 
00793 //: vcl_vector<double>
00794 VDS void settype(vul_arg<vcl_vector<double> > &argmt) {argmt.type_ = "double list";}
00795 
00796 VDS void print_value(vcl_ostream &s, vul_arg<vcl_vector<double> > const &argmt)
00797 {
00798   for (unsigned int i=0; i<argmt().size(); ++i)
00799     s << ' ' << argmt()[i];
00800 }
00801 
00802 VDS int parse(vul_arg<vcl_vector<double> >* argmt, char ** argv)
00803 {
00804   if ( !argv ||  !argv[0] ) {
00805     // no input
00806     vcl_cerr << "vul_arg_parse: Expected a vector of floating number, none is provided.\n";
00807     return -1;
00808   }
00809 
00810   int sucked = 0;
00811   // Defaults should be cleared when the user supplies a value
00812   argmt->value_.clear();
00813   char *current = argv[0];
00814   while (current) {
00815     char* endptr = 0;
00816     double tmp = vcl_strtod(current, &endptr);
00817     //argmt->value_
00818     if (*endptr == '\0') {
00819       argmt->value_.push_back(tmp);
00820       ++ sucked;
00821       ++ argv;
00822       current = argv[0];
00823     }
00824     else if (*endptr == ',')
00825     {
00826       argmt->value_.push_back(tmp);
00827       current = endptr+1;
00828     }
00829     else if (endptr == current)
00830       break; // OK. end of list of doubles.
00831     else {
00832       // There is junk after the number, or no number was found
00833       vcl_cerr << "vul_arg_parse: WARNING: Attempt to parse " << current << " as double\n";
00834       return -1;
00835     }
00836   }
00837   return sucked;
00838 }
00839 
00840 template class vul_arg<vcl_vector<double> >;