argparser.cpp
00001 00002 /*************************************************************************** 00003 * argparser.cpp - Implementation of the argument parser 00004 * 00005 * Generated: Mon May 30 13:25:33 2005 (from FireVision) 00006 * Copyright 2005-2006 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <utils/system/argparser.h> 00025 #include <core/exceptions/software.h> 00026 #include <libgen.h> 00027 #include <cstdio> 00028 #include <cstdlib> 00029 #include <cstring> 00030 00031 namespace fawkes { 00032 00033 /** @class ArgumentParser utils/system/argparser.h 00034 * Parse command line arguments. 00035 * Interface to GNU getopt and getopt_long. Parses command line arguments and 00036 * separates long and short options. 00037 * 00038 * The supplied opt_string is a string containing the legitimate option 00039 * characters. A character c denotes an option of the type "-c" (single dash). 00040 * If such a character is followed by a colon, the option requires an argument, 00041 * Two colons mean an option takes an optional arg. 00042 * 00043 * If long_options is supplied options started out by two dashes are recognized. 00044 * Long option names may be abbreviated if the abbreviation is unique or is an 00045 * exact match for some defined option. A long option may take a parameter, of 00046 * the form --arg=param or --arg param. 00047 * 00048 * long_options is a pointer to the first element of an array of struct option 00049 * declared in <getopt.h> as 00050 * 00051 * @code 00052 * struct option { 00053 * const char *name; 00054 * int has_arg; 00055 * int *flag; 00056 * int val; 00057 * }; 00058 * @endcode 00059 * 00060 * The meanings of the different fields are: 00061 * 00062 * name is the name of the long option. 00063 * 00064 * has_arg is: no_argument (or 0) if the option does not take an argument; 00065 * required_argument (or 1) if the option requires an argument; 00066 * or optional_argument (or 2) if the option takes an optional argument. 00067 * 00068 * flag specifies how results are returned for a long option. If flag is 00069 * NULL, then getopt_long() returns val. (For example, the calling 00070 * program may set val to the equivalent short option character.) 00071 * Otherwise, getopt_long() returns 0, and flag points to a variable 00072 * which is set to val if the option is found, but left unchanged if the 00073 * option is not found. Handled internally in ArgumentParser 00074 * 00075 * For more information see man 3 getopt. 00076 * 00077 * All arguments that do not belong to parsed options are stored as items and can 00078 * be retrieved via items(). 00079 */ 00080 00081 00082 /** Constructor 00083 * @param argc argument count. 00084 * @param argv argument vector 00085 * @param opt_string option string, see ArgumentParser 00086 * @param long_options long options, see ArgumentParser 00087 */ 00088 ArgumentParser::ArgumentParser(int argc, char **argv, const char *opt_string, option *long_options) 00089 { 00090 _argc = argc; 00091 _argv = argv; 00092 00093 _opts.clear(); 00094 _items.clear(); 00095 00096 #ifdef _GNU_SOURCE 00097 _program_name = strdup(basename( argv[0] )); 00098 #else 00099 // Non-GNU variants may modify the sting in place 00100 char *tmp = strdup(argv[0]); 00101 _program_name = strdup(basename(tmp)); 00102 free(tmp); 00103 #endif 00104 00105 if (long_options == NULL) { 00106 int c ; 00107 char tmp[2]; 00108 00109 while ((c = getopt(argc, argv, opt_string)) != -1) { 00110 if (c == '?') { 00111 throw UnknownArgumentException(c); 00112 } else if (c == ':') { 00113 throw MissingArgumentException(c); 00114 } 00115 sprintf(tmp, "%c", c); 00116 _opts[ tmp ] = optarg; 00117 } 00118 } else { 00119 int opt_ind = 0; 00120 int c; 00121 while ((c = getopt_long(argc, argv, opt_string, long_options, &opt_ind)) != -1) { 00122 if (c == '?') { 00123 throw UnknownArgumentException(c); 00124 } else if (c == 0) { 00125 // long options 00126 _opts[ long_options[opt_ind].name ] = optarg; 00127 } else { 00128 char tmp[2]; 00129 sprintf(tmp, "%c", c); 00130 _opts[ tmp ] = optarg; 00131 } 00132 } 00133 } 00134 00135 _items.clear(); 00136 int ind = optind; 00137 while (ind < argc) { 00138 _items.push_back( argv[ind++] ); 00139 } 00140 00141 } 00142 00143 00144 /** Destructor. */ 00145 ArgumentParser::~ArgumentParser() 00146 { 00147 free(_program_name); 00148 _opts.clear(); 00149 } 00150 00151 00152 /** Check if argument has been supplied. 00153 * @param argn argument name to check for 00154 * @return true, if the argument was given on the command line, false otherwise 00155 */ 00156 bool 00157 ArgumentParser::has_arg(const char *argn) 00158 { 00159 return (_opts.count((char *)argn) > 0); 00160 } 00161 00162 00163 /** Get argument value. 00164 * Use this method to get the value supplied to the given option. 00165 * @param argn argument name to retrieve 00166 * @return the argument value. Pointer to static program array. Do not free! 00167 * Returns NULL if argument was not supplied on command line. 00168 */ 00169 const char * 00170 ArgumentParser::arg(const char *argn) 00171 { 00172 if (_opts.count((char *)argn) > 0) { 00173 return _opts[ (char *)argn ]; 00174 } else { 00175 return NULL; 00176 } 00177 } 00178 00179 00180 /** Get argument while checking availability. 00181 * The argument will be a newly allocated copy of the string. You have to 00182 * free it after you are done with it. 00183 * @param argn argument name to retrieve 00184 * @param value a pointer to a newly allocated copy of the argument value will 00185 * be stored here if the argument has been found. 00186 * The value is unchanged if argument was not supplied. 00187 * @return true, if the argument was supplied, false otherwise 00188 */ 00189 bool 00190 ArgumentParser::arg(const char *argn, char **value) 00191 { 00192 if (_opts.count((char *)argn) > 0) { 00193 *value = strdup(_opts[ (char *)argn ]); 00194 return true; 00195 } else { 00196 return false; 00197 } 00198 } 00199 00200 00201 /** Parse host:port string. 00202 * The value referenced by the given argn is parsed for the pattern "host:port". If the 00203 * string does not match this pattern an exception is thrown. 00204 * The host will be a newly allocated copy of the string. You have to 00205 * free it after you are done with it. If no port is supplied in the string (plain 00206 * hostname string) the port argument is left unchanged. If the argument has not 00207 * been supplied at all both values are left unchanged. Thus it is safe to put the default 00208 * values into the variables before passing them to this method. Note however that you 00209 * have to free the returned host string in case of a successful return, and only in 00210 * that case probably! 00211 * @param argn argument name to retrieve 00212 * @param host Upon successful return contains a pointer to a newly alloated string 00213 * with the hostname part. Free it after you are finished. 00214 * @param port upon successful return contains the port part 00215 * @return true, if the argument was supplied, false otherwise 00216 * @exception OutOfBoundsException thrown if port is not in the range [0..65535] 00217 */ 00218 bool 00219 ArgumentParser::parse_hostport(const char *argn, char **host, unsigned short int *port) 00220 { 00221 if (_opts.count((char *)argn) > 0) { 00222 char *tmpvalue = strdup(_opts[ (char *)argn ]); 00223 00224 if ( strchr(tmpvalue, ':') != NULL ) { 00225 char *save_ptr; 00226 *host = strtok_r(tmpvalue, ":", &save_ptr); 00227 char *tmpport = strtok_r(NULL, "", &save_ptr); 00228 00229 int port_num = atoi(tmpport); 00230 if ( (port_num < 0) || (port_num > 0xFFFF) ) { 00231 throw OutOfBoundsException("Invalid port", port_num, 0, 0xFFFF); 00232 } 00233 *port = port_num; 00234 } else { 00235 *host = tmpvalue; 00236 } 00237 00238 return true; 00239 } else { 00240 return false; 00241 } 00242 } 00243 00244 00245 /** Parse argument as integer. 00246 * Converts the value of the given argument to an integer. 00247 * @param argn argument name to retrieve 00248 * @return value of string as long int 00249 * @exception IllegalArgumentException thrown if the value cannot be properly 00250 * converted to an integer 00251 * @exception Exception thrown if the argument has not been supplied 00252 */ 00253 long int 00254 ArgumentParser::parse_int(const char *argn) 00255 { 00256 if (_opts.count((char *)argn) > 0) { 00257 char *endptr; 00258 long int rv = strtol(_opts[argn], &endptr, 10); 00259 if ( endptr[0] != 0 ) { 00260 throw IllegalArgumentException("Supplied argument is not of type int"); 00261 } 00262 return rv; 00263 } else { 00264 throw Exception("Value for '%s' not available", argn); 00265 } 00266 } 00267 00268 00269 /** Parse argument as double. 00270 * Converts the value of the given argument to a double. 00271 * @param argn argument name to retrieve 00272 * @return value of string as double 00273 * @exception IllegalArgumentException thrown if the value cannot be properly 00274 * converted to a double 00275 * @exception Exception thrown if the argument has not been supplied 00276 */ 00277 double 00278 ArgumentParser::parse_float(const char *argn) 00279 { 00280 if (_opts.count((char *)argn) > 0) { 00281 char *endptr; 00282 double rv = strtod(_opts[argn], &endptr); 00283 if ( endptr[0] != 0 ) { 00284 throw IllegalArgumentException("Supplied argument is not of type double"); 00285 } 00286 return rv; 00287 } else { 00288 throw Exception("Value for '%s' not available", argn); 00289 } 00290 } 00291 00292 00293 /** Parse item as integer. 00294 * Converts the value of the given item to an integer. 00295 * @param index item index 00296 * @return value of string as long int 00297 * @exception IllegalArgumentException thrown if the value cannot be properly 00298 * converted to an integer 00299 * @exception Exception thrown if the argument has not been supplied 00300 */ 00301 long int 00302 ArgumentParser::parse_item_int(unsigned int index) 00303 { 00304 if (index < _items.size()) { 00305 char *endptr; 00306 long int rv = strtol(_items[index], &endptr, 10); 00307 if ( endptr[0] != 0 ) { 00308 throw IllegalArgumentException("Supplied argument is not of type int"); 00309 } 00310 return rv; 00311 } else { 00312 throw Exception("Value for item %u not available", index); 00313 } 00314 } 00315 00316 00317 /** Parse item as double. 00318 * Converts the value of the given item to a double. 00319 * @param index item index 00320 * @return value of string as double 00321 * @exception IllegalArgumentException thrown if the value cannot be properly 00322 * converted to a double 00323 * @exception Exception thrown if the argument has not been supplied 00324 */ 00325 double 00326 ArgumentParser::parse_item_float(unsigned int index) 00327 { 00328 if (index < _items.size()) { 00329 char *endptr; 00330 double rv = strtod(_items[index], &endptr); 00331 if ( endptr[0] != 0 ) { 00332 throw IllegalArgumentException("Supplied argument is not of type double"); 00333 } 00334 return rv; 00335 } else { 00336 throw Exception("Value for item %u not available", index); 00337 } 00338 } 00339 00340 00341 /** Get non-option items. 00342 * @return pointer to vector of pointer to non-argument values. Handled internally, 00343 * do not free or delete! 00344 */ 00345 const std::vector< const char* > & 00346 ArgumentParser::items() const 00347 { 00348 return _items; 00349 } 00350 00351 00352 /** Get number of non-option items. 00353 * @return number of non-opt items. 00354 */ 00355 std::vector< const char* >::size_type 00356 ArgumentParser::num_items() const 00357 { 00358 return _items.size(); 00359 } 00360 00361 00362 /** Get number of arguments. 00363 * @return number of arguments 00364 */ 00365 int 00366 ArgumentParser::argc() const 00367 { 00368 return _argc; 00369 } 00370 00371 00372 /** Program argument array as supplied to constructor. 00373 * @return argument array. 00374 */ 00375 const char ** 00376 ArgumentParser::argv() const 00377 { 00378 return (const char **)_argv; 00379 } 00380 00381 00382 /** Get name of program. 00383 * @return the name of the program (argv[0] of argument vector supplied to constructor). 00384 */ 00385 const char * 00386 ArgumentParser::program_name() const 00387 { 00388 return _program_name; 00389 } 00390 00391 } // end namespace fawkes

