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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2