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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2