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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2