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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2