(file) Return to getoopt.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / getoopt

  1 bob   1.2 //BEGIN_LICENSE
  2           //
  3           // Copyright (c) 2000 The Open Group, BMC Software, Tivoli Systems, IBM
  4           //
  5           // Permission is hereby granted, free of charge, to any person obtaining a
  6           // copy of this software and associated documentation files (the "Software"),
  7           // to deal in the Software without restriction, including without limitation
  8           // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9           // and/or sell copies of the Software, and to permit persons to whom the
 10           // Software is furnished to do so, subject to the following conditions:
 11           //
 12           // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 13           // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 14           // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 15           // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 16           // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 17           // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 18           // DEALINGS IN THE SOFTWARE.
 19           //
 20           //END_LICENSE
 21           //BEGIN_HISTORY
 22 bob   1.2 //
 23           // Author: Bob Blair bblair@bmc.com
 24           //
 25           // $Log: 
 26           // 
 27           //
 28           //END_HISTORY
 29 bob   1.1 //
 30           // implementation of getoopt
 31           
 32           #include "getoopt.h"
 33           #include <string.h>
 34           
 35           using namespace std;
 36           
 37           //-----------------------------------------------------------------------
 38           //              Implementation of class Optarg
 39           // An Optarg is created for each parameter on the command line.
 40           //-----------------------------------------------------------------------
 41           
 42           // Constructors
 43           //   Default Constructor
 44           Optarg::Optarg() : _name(""), _opttype(REGULAR), _value("") {
 45           }
 46           
 47           //   All-in-one
 48           Optarg::Optarg(const string &name, opttype type, const string &value) :
 49             _name(name), _opttype(type), _value(value) {
 50 bob   1.1 }
 51           
 52           // Destructor
 53           Optarg::~Optarg() {};
 54           
 55           //-----------------------------------------------------------------------
 56           //        Set the class members
 57           //-----------------------------------------------------------------------
 58           
 59           // Set the _name member
 60           void
 61           Optarg::setName(const string &name) {
 62             _name = name;
 63           }
 64           
 65           // Set the _opttype member
 66           void
 67           Optarg::setType(opttype type) {
 68             _opttype = type;
 69           }
 70           
 71 bob   1.1 // Set the _value member
 72           void
 73           Optarg::setValue(const string &value) {
 74             _value = value;
 75           }
 76           
 77           //-----------------------------------------------------------------------
 78           //      Retrieve class members
 79           //-----------------------------------------------------------------------
 80           
 81           //  Get the _name member
 82           const string &
 83           Optarg::getName() const { return _name; }
 84           
 85           //  Get the _name member using getopt() terminology
 86           const string &
 87           Optarg::getopt()  const { return _name; }
 88           
 89           //  Get the _type member
 90           Optarg::opttype 
 91           Optarg::getType() const { return _opttype; }
 92 bob   1.1 
 93           //-------------------------------------------------------------------
 94           //             Ways to get the _value member
 95           //-------------------------------------------------------------------
 96           
 97           //  Return _value as const string ref
 98           const string &
 99           Optarg::Value() const { return _value; }
100           
101           //  Same thing as Value(), but using getopt() terminology
102           const string &
103           Optarg::optarg() const { return _value; }
104           
105           //  Fill in a caller-provided string
106           void
107           Optarg::Value(string &s) const { s = _value; }
108           
109           //  Fill in a caller-provided int with the integer conversion of the value.
110           void
111           Optarg::Value(int &i) const { i = (int)atoi(_value.c_str()); }
112           
113 bob   1.1 //  Fill in a caller-provided unsigned int
114           void
115           Optarg::Value(unsigned int &i) const {
116             i = (unsigned int)atoi(_value.c_str());
117           }
118           
119           //  Fill in a call-provided unsigned int
120           void
121           Optarg::Value(long &l) const {
122             l = (long)atoi(_value.c_str());
123           }
124           
125           //  Fill in a caller-provided long
126           void
127           Optarg::Value(unsigned long &l) const {
128             l = (unsigned long)atoi(_value.c_str());
129           }
130           
131           //  Ditto unsigned long
132           void
133           Optarg::Value(double &d) const {
134 bob   1.1   d = (double)atof(_value.c_str());
135           }
136           
137           //--------------------------------------------------------------------
138           //  Provide information about the flag, if any
139           //--------------------------------------------------------------------
140           
141           // Is the option value is bound to a flag?
142           bool
143           Optarg::isFlag() const { return (_opttype == FLAG || _opttype == LONGFLAG); }
144           
145           // Is it bound to a long-named flag?
146           bool
147           Optarg::isLongFlag() const { return (_opttype == LONGFLAG); }
148           
149           //-----------------------------------------------------------------------
150           //  print the members as a formatted string
151           //-----------------------------------------------------------------------
152           ostream &
153           Optarg::print(ostream &os) const {
154             os << "{name:(" << getName();
155 bob   1.1   os << ") type:(";
156             switch (getType()) {
157             case FLAG: os << "FLAG"; break;
158             case LONGFLAG: os << "LONGFLAG"; break;
159             case REGULAR: os << "REGULAR"; break;
160             }
161             os << ") value:(" << Value() << ")}";
162             return os;
163           }
164           
165           
166           
167           //---------------------------------------------------------------------
168           //                   Implementation of class getoopt
169           //---------------------------------------------------------------------
170           
171           // Constructors and destructor
172           
173           // Default constructor.  The optional string is in the format of
174           // a getopt() optstring 
175           getoopt::getoopt(const char *optstring)
176 bob   1.1 {
177             if (optstring) {
178               addFlagspec(optstring);
179             }
180           }
181           
182           getoopt::~getoopt() {;}
183           
184           //----------------------------------------------------------------------
185           //  methods to register program-defined flags and their characteristics
186           //  The flags are encapsulated in the struct flagspec, an array of which
187           //  is a member of this class.
188           //  There are also methods to deregister flags. This is done by resetting
189           //  a flagspec's active flag.
190           //----------------------------------------------------------------------
191           
192           // Parse through a getopt() optstring and create flagspecs from each
193           // short flag.
194           bool
195           getoopt::addFlagspec(const string &opt) {
196             unsigned int size = opt.size();
197 bob   1.1   if (size == 0)
198               return false;
199             for (unsigned int i = 0; i < size; i++) {
200               char c = opt[i];
201               if ( ((i + 1) < size) && (opt[i+1] == ':') ) {
202                 if (!(addFlagspec(c, true))) {
203           	  return false;
204                 }
205                 ++i;
206               } else {
207                 if (!(addFlagspec(c, false)))
208           	return false;
209               }
210             }
211             return true;
212           }
213           
214           //  Create a filespec from a single short flag and push it onto the array
215           bool
216           getoopt::addFlagspec(char flag, bool hasarg) {
217             if (flag == '*') {
218 bob   1.1     addError("You can't have a flag named '*'");
219               return false;
220             }
221             flagspec fs;
222             char c[2];
223             c[0] = flag;
224             c[1] = 0;
225             fs.name = c;
226             fs.argtype = hasarg ? 1 : 0;
227             fs.islong = false;
228             fs.active = true;
229             _flagspecs.push_back(fs);
230             return true;
231           }
232           
233           // Create a flagspec from a single long flag and push it onto the array
234           bool
235           getoopt::addLongFlagspec(const string &name, argtype type) {
236             flagspec fs;
237             fs.name = name;
238             fs.argtype = type;
239 bob   1.1   fs.islong = true;
240             fs.active = true;
241             _flagspecs.push_back(fs);
242             return true;
243           }
244           
245           // Unregister a flagspec
246           bool
247           getoopt::removeFlagspec(char opt) {
248             flagspec *fs = getFlagspecForUpdate(opt);
249             if (fs) {
250               fs->active = false;
251               return true;
252             }
253             return false;
254           }
255           
256           //--------------------------------------------------------------------
257           //      Routines for parsing the command line
258           //--------------------------------------------------------------------
259           
260 bob   1.1 //------------------------
261           // Static functions
262           //------------------------
263           
264           // Parse out the flagname and the value from a long flag option that
265           // may be in the form
266           //          --longflag=value
267           static void
268           partsFromLongOpt (const string &s, string &name, string &value) {
269             for (unsigned int i = 0; i < s.size(); i++) {
270               if (s[i] == '=') {
271                 name = s.substr(0, i);
272                 value = s.substr(i+1);
273                 return;
274               }
275             }
276             name = s;
277             value =  "";
278           }
279           
280           // Create an Optarg instance from a long flag string like
281 bob   1.1 //          --longflag=value
282           // (The =value is optional).
283           static void 
284           optargFromLongOpt(Optarg &o, const string &arg) {
285             string name;
286             string value;
287             partsFromLongOpt(arg, name, value);
288             o.setName(name);
289             o.setType(Optarg::LONGFLAG);
290             o.setValue(value);
291           }
292           
293           // Create an Optarg instance from a short flag string like
294           //      -fValue
295           // (The Value part is optional)
296           static void
297           optargFromShortOpt(Optarg &o, const char *arg) {
298             char name[2];
299             name[0] = arg[0];
300             name[1] = 0;
301             o.setName(name);
302 bob   1.1   o.setType(Optarg::FLAG);
303             const char *p = arg + 1;
304             o.setValue(p);
305           }
306           
307           // Look at a command line option and determine whether it is a
308           // long flag, a short flag or an unflagged option.
309           static int
310           catagorize(const char *s) {
311             if (s[0] != '-')
312               return 0;
313             else
314               if (s[1] == '-')
315                 return 2;
316             return 1;
317           }
318           
319           // Push an Optarg onto our array
320           static void
321           addarg(getoopt::Arg_List&list, const Optarg &o) {
322             //o.print(cout);
323 bob   1.1   list.push_back(o);
324           }
325           
326           // Create an Optarg from its members and push it onto the array
327           static void
328           addarg(getoopt::Arg_List&list, const string &name, Optarg::opttype type,
329           	      const string &value) {
330             Optarg *o = new Optarg(name, type, value);
331             addarg(list, *o);
332             delete o;
333           }
334           
335           // Take an array of arguments and append it to another
336           static void
337           copyargs(getoopt::Arg_List &out, const getoopt::Arg_List &in) {
338             for (getoopt::Arg_List::const_iterator it = in.begin(); 
339                  it != in.end();
340                  it++) {
341               addarg(out, *it);
342             }
343           }
344 bob   1.1 
345           //------------------------------------
346           // The parse method:  Way too long.
347           // Note that flag args are pushed
348           // onto the stack, then the regular
349           // args are appended, sorting them
350           // to the rear the way getopt() does.
351           //------------------------------------
352           bool
353           getoopt::parse(int argc, char **argv) {
354             Optarg o;
355             int cat;
356             const flagspec *fs;
357             Arg_List nonflagargs;
358             enum states {START, ARGEXPECTED};
359             states state = START;
360             for (unsigned int i = 1; i < (unsigned int)argc; i++) {
361               unsigned int endsize = strlen(argv[i]);
362                 switch (state) {
363                 case START:
364                   cat = catagorize(argv[i]);
365 bob   1.1 	switch (cat) {
366           	case 0: // non-flag command line argument
367           	  addarg(nonflagargs, "", Optarg::REGULAR, argv[i]);
368           	  break;
369           	case 1: // short (1-character) flag
370           	  {
371           	    unsigned int argpos = 1;
372           	    while (argpos < endsize) {
373           	      char c = argv[i][argpos];
374           	      fs = getFlagspec(c);  // Short flag
375           	      string temp = argv[i];
376           	      string name = temp.substr(argpos, 1);
377           	      if (!fs) {  // See if we recognize it
378           		addError("Unknown flag -" + name);
379           		argpos++;
380           	      } else {
381           		if (fs->argtype == NOARG) {  // Should this flag be bound
382           		  addarg(_args, name, Optarg::FLAG,  "");  // NO
383           		  argpos++;
384           		} else { // YES -- the value is here or in the next arg
385           		  optargFromShortOpt(o, &argv[i][argpos]);
386 bob   1.1 		  if (o.Value() == "") { // No value yet
387           		    state = ARGEXPECTED;
388           		  } else {
389           		    addarg(_args, o);
390           		  }
391           		  argpos = endsize;
392           		}
393           	      }
394           	    }
395           	  } // end subcase 1
396           	  break;
397           	case 2:  // long (--xyz) flag
398           	  { 
399           	    string arg = &(argv[i][2]);
400           	    optargFromLongOpt(o, arg);
401           	    fs = getFlagspec(o.getName());
402           	    if (!fs) { // see if we recognize this flag
403           	      string temp = "Unknown flag ";
404           	      addError(temp + o.getName());
405           	    } else {
406           	        // this is a long flag we know about
407 bob   1.1 	      if (o.optarg() != ""  || fs->argtype != MUSTHAVE) { 
408           		addarg(_args, o);
409           		state = START;  // we have a completed long flag
410           	      } else {   // no value yet, and we expect one
411           		if (fs->argtype == MUSTHAVE) {
412           		  state = ARGEXPECTED;
413           		}
414           	      }
415           	    }
416           	    break;
417           	  } // end subcase 2
418           	} // end switch catagorize()
419           	break; // end of case START
420           
421                 case ARGEXPECTED:
422           	if (argv[i][0] == '-') {
423           	  addError("Missing required value for flag " + o.getopt());
424           	  i--;
425           	} else {
426           	  o.setValue(argv[i]);
427           	}
428 bob   1.1 	addarg(_args, o);
429           	state = START;
430           	break;
431                 } // end switch
432             } // end for
433             if (state != START) {
434               addError("Missing required value for flag " + o.getName());
435             }
436             copyargs(_args, nonflagargs);
437             return !_errorStrings.size();
438           }
439           
440           //----------------------------------------------------------------------
441           //         Methods to retrieve the command line arguments
442           //----------------------------------------------------------------------
443           
444           //----------------------------------------------
445           // Access the command line arguments by index
446           //----------------------------------------------
447           
448           // Index operator
449 bob   1.1 const Optarg &
450           getoopt::operator[](unsigned int n) {
451             unsigned int lim = _args.size();
452             if (n < lim) 
453               return _args[n];
454             else
455               return _emptyopt;
456           }
457           
458           // Return first index
459           unsigned int
460           getoopt::first() const { return 0; }
461           
462           // Return one past last index
463           unsigned int
464           getoopt::last() const { return _args.size(); }
465           
466           //-----------------------------------------------
467           // Access the command line arguments using
468           // getoopt::const_iterator
469           //-----------------------------------------------
470 bob   1.1 
471           Optarg *
472           getoopt::begin() {
473             return _args.begin();
474           }
475           
476           Optarg *
477           getoopt::end() {
478             return _args.end();
479           }
480           
481           //-----------------------------------------------
482           // Access the command line arguments ad-hoc
483           //-----------------------------------------------
484           
485           // Return the number of times a short flag is set
486           // on the command line
487           unsigned int
488           getoopt::isSet(char c) const {
489             unsigned int cnt = 0;
490             for (unsigned int i = 0; i < _args.size(); i++) {
491 bob   1.1     const Optarg &o = _args[i];
492               if (o.getType() == Optarg::FLAG) {
493                 const string &s = o.getopt();
494                 if (s[0] == c) {
495           	cnt++;
496                 }
497               }
498             }
499             return cnt;
500           }
501           
502           // Return the number of times any flag is set
503           // on the command line
504           unsigned int
505           getoopt::isSet(const string &s) const {
506             unsigned int cnt = 0;
507             for (unsigned int i = 0; i < _args.size(); i++) {
508               const Optarg &o = _args[i];
509               if (o.optarg() == s) {
510                 cnt++;
511               }
512 bob   1.1   }
513             return cnt;
514           }
515           
516           // Return the string value of the nth instance of
517           // a particular short flag on the command line
518           const string &
519           getoopt::value(char opt, unsigned int idx) const {
520             unsigned int cnt = 0;
521             for (unsigned int i = 0; i < _args.size(); i++) {
522               const Optarg &o = _args[i];
523               if (o.getType() == Optarg::FLAG) {
524                 const string &s = o.getopt();
525                 if (s[0] == opt) {
526           	if (cnt == idx) {
527           	  return o.optarg();
528           	} else {
529           	  cnt++;
530           	}
531                 }
532               }
533 bob   1.1   }
534             return(emptystring);
535           }
536           
537           // Return the nth instance of any flag on the command line
538           const string &
539           getoopt::value(const string &opt, unsigned int idx) const {
540             unsigned int cnt = 0;
541             for (unsigned int i = 0; i < _args.size(); i++) {
542               const Optarg &o = _args[i];
543               if (o.optarg() == opt) {
544                 if (cnt == idx) {
545           	return o.getopt();
546                 } else {
547           	cnt++;
548                 }
549               }
550             }
551             return(emptystring);
552           }
553           
554 bob   1.1 // Of the command line arguments, how many are flags?
555           unsigned int
556           getoopt::flagcnt() const {
557             unsigned int cnt = 0;
558             for (Arg_List::const_iterator it = _args.begin();
559                  it != _args.end();
560                  it++) {
561               if (it->getType() != Optarg::REGULAR)
562                 cnt++; 
563             }
564             return cnt;
565           }
566           
567           // How many command line arguments were there?
568           unsigned int
569           getoopt::size() const {
570             return _args.size();
571           }
572           
573           // Return the list of command line arguments for use by
574           // the program.
575 bob   1.1 const getoopt::Arg_List &
576           getoopt::getArgs() const { return _args; }
577           
578           
579           //-----------------------------------------------------------
580           // Routines dealing with errors during parsing
581           // FIXME:  This needs to be reworked so that the error text
582           // is hidden and provided by the caller
583           //----------------------------------------------------------
584           
585           // Add an error into the list
586           void
587           getoopt::addError(const string &s)
588           {
589             _errorStrings.push_back(s);
590           }
591           
592           // Return a list of the errors
593           const getoopt::Error_List &
594           getoopt::getErrorStrings() const {
595             return _errorStrings;
596 bob   1.1 }
597           
598           // Did any errors occur?
599           bool
600           getoopt::hasErrors() const {
601             return _errorStrings.size() ? true : false;
602           }
603           
604           
605           
606           flagspec *
607           getoopt::getFlagspecForUpdate(const string &s) {
608             for (unsigned int i = 0; i < _flagspecs.size(); i++) {
609               flagspec &o = _flagspecs[i];
610               if (o.islong && s == o.name)
611                 return &_flagspecs[i];
612             }
613           return 0;
614           }
615           
616           const flagspec *
617 bob   1.1 getoopt::getFlagspec(const string &s) {
618             return (const flagspec *)getFlagspecForUpdate(s);
619           }
620           
621           ostream &
622           getoopt::printErrors(ostream &os) const {
623             for (Error_List::const_iterator it = _errorStrings.begin();
624                  it != _errorStrings.end();
625                  it++) {
626               os << "> " << *it << endl;
627             }
628             return os;
629           }
630           
631           //---------------------------------------------------------------
632           //              Private methods
633           //---------------------------------------------------------------
634           flagspec *
635           getoopt::getFlagspecForUpdate(char c) {
636             for (unsigned int i = 0; i < _flagspecs.size(); i++) {
637               flagspec &o = _flagspecs[i];
638 bob   1.1     if (!o.islong && c == o.name[0])
639                 return &_flagspecs[i];
640             }
641             return 0;
642           }
643           
644           const flagspec *
645           getoopt::getFlagspec(char c) {
646             return (const flagspec *)getFlagspecForUpdate(c);
647           }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2