(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 kumpf 1.20 void Optarg::Value (int &i) const  throw (IncompatibleTypesException)
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 kumpf 1.20             throw IncompatibleTypesException ();
136 mike  1.14         }
137                }
138                else
139                {
140 kumpf 1.20         throw IncompatibleTypesException ();
141 mike  1.14     }
142 mike  1.13 }
143            
144            //  Fill in a caller-provided unsigned int
145 kumpf 1.20 void Optarg::Value (unsigned int &i) const throw (IncompatibleTypesException)
146 mike  1.14 {
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 kumpf 1.20             throw IncompatibleTypesException ();
165 mike  1.14         }
166                }
167                else
168                {
169 kumpf 1.20         throw IncompatibleTypesException ();
170 mike  1.14     }
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 kumpf 1.21   Uint32 size = in.size();
407              for (Uint32 i = 0; i < size; i++) {
408                addarg(out, in[i]);
409 mike  1.13   }
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              for (unsigned int i = 1; i < (unsigned int)argc; i++) {
428                unsigned int endsize = strlen(argv[i]);
429                  switch (state) {
430 mike  1.13       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            		if (fs->argtype == NOARG) {  // Should this flag be bound
449            		  addarg(_args, name, Optarg::FLAG,  "");  // NO
450            		  argpos++;
451 mike  1.13 		} 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            	    if (!fs) { // see if we recognize this flag
470            	      String temp = "Unknown flag ";
471            	      addError(temp + o.getName());
472 mike  1.13 	    } else {
473            	        // this is a long flag we know about
474 kumpf 1.16 	      if (o.optarg() != ""  || fs->argtype != MUSTHAVEARG) { 
475 mike  1.13 		addarg(_args, o);
476            		state = START;  // we have a completed long flag
477            	      } else {   // no value yet, and we expect one
478 kumpf 1.16 		if (fs->argtype == MUSTHAVEARG) {
479 mike  1.13 		  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            	  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 mike  1.13   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            //----------------------------------------------
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 mike  1.13   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            
533            //-----------------------------------------------
534            // Access the command line arguments ad-hoc
535            //-----------------------------------------------
536            
537            // Return the number of times a short flag is set
538            // on the command line
539            unsigned int
540            getoopt::isSet(char c) const {
541              unsigned int cnt = 0;
542 mike  1.13   for (unsigned int i = 0; i < _args.size(); i++) {
543                const Optarg &o = _args[i];
544                if (o.getType() == Optarg::FLAG) {
545                  const String &s = o.getopt();
546                  if (s[0] == c) {
547            	cnt++;
548                  }
549                }
550              }
551              return cnt;
552            }
553            
554            // Return the number of times any flag is set
555            // on the command line
556            unsigned int
557            getoopt::isSet(const String &s) const {
558              unsigned int cnt = 0;
559              for (unsigned int i = 0; i < _args.size(); i++) {
560                const Optarg &o = _args[i];
561                if (o.getopt() == s) {
562                  cnt++;
563 mike  1.13     }
564              }
565              return cnt;
566            }
567            
568            // Return the String value of the nth instance of
569            // a particular short flag on the command line
570            const String &
571            getoopt::value(char opt, unsigned int idx) const {
572              unsigned int cnt = 0;
573              for (unsigned int i = 0; i < _args.size(); i++) {
574                const Optarg &o = _args[i];
575                if (o.getType() == Optarg::FLAG) {
576                  const String &s = o.getopt();
577                  if (s[0] == opt) {
578            	if (cnt == idx) {
579            	  return o.optarg();
580            	} else {
581            	  cnt++;
582            	}
583                  }
584 mike  1.13     }
585              }
586              return(emptystring);
587            }
588            
589            // Return the nth instance of any flag on the command line
590            const String &
591            getoopt::value(const String &opt, unsigned int idx) const {
592              unsigned int cnt = 0;
593              for (unsigned int i = 0; i < _args.size(); i++) {
594                const Optarg &o = _args[i];
595                if (o.optarg() == opt) {
596                  if (cnt == idx) {
597            	return o.getopt();
598                  } else {
599            	cnt++;
600                  }
601                }
602              }
603              return(emptystring);
604            }
605 mike  1.13 
606            // Of the command line arguments, how many are flags?
607            unsigned int
608            getoopt::flagcnt() const {
609              unsigned int cnt = 0;
610 kumpf 1.21   for (Uint32 i = 0; i < _args.size(); i++) {
611                if (_args[i].getType() != Optarg::REGULAR)
612 mike  1.13       cnt++; 
613              }
614              return cnt;
615            }
616            
617            // How many command line arguments were there?
618            unsigned int
619            getoopt::size() const {
620              return _args.size();
621            }
622            
623            // Return the list of command line arguments for use by
624            // the program.
625            const getoopt::Arg_List &
626            getoopt::getArgs() const { return _args; }
627            
628            
629            //-----------------------------------------------------------
630            // Routines dealing with errors during parsing
631            // FIXME:  This needs to be reworked so that the error text
632            // is hidden and provided by the caller
633 mike  1.13 //----------------------------------------------------------
634            
635            // Add an error into the list
636            void
637            getoopt::addError(const String &s)
638            {
639              _errorStrings.append(s);
640            }
641            
642            // Return a list of the errors
643            const getoopt::Error_List &
644            getoopt::getErrorStrings() const {
645              return _errorStrings;
646            }
647            
648            // Did any errors occur?
649            Boolean
650            getoopt::hasErrors() const {
651              return _errorStrings.size() ? true : false;
652            }
653            
654 mike  1.13 
655            
656            flagspec *
657            getoopt::getFlagspecForUpdate(const String &s) {
658              for (unsigned int i = 0; i < _flagspecs.size(); i++) {
659                flagspec &o = _flagspecs[i];
660                if (o.islong && s == o.name)
661                  return &_flagspecs[i];
662              }
663            return 0;
664            }
665            
666            const flagspec *
667            getoopt::getFlagspec(const String &s) {
668              return (const flagspec *)getFlagspecForUpdate(s);
669            }
670            
671            ostream &
672            getoopt::printErrors(ostream &os) const {
673 kumpf 1.21   for (Uint32 i = 0; i < _errorStrings.size(); i++) {
674                os << "> " << _errorStrings[i] << endl;
675 mike  1.13   }
676              return os;
677            }
678            
679            void
680            getoopt::printErrors(String &s) const {
681 kumpf 1.21   for (Uint32 i = 0; i < _errorStrings.size(); i++) {
682                s += "> " + _errorStrings[i] + "\n";
683 mike  1.13   }
684            }
685            
686            //---------------------------------------------------------------
687            //              Private methods
688            //---------------------------------------------------------------
689            flagspec *
690            getoopt::getFlagspecForUpdate(char c) {
691              for (unsigned int i = 0; i < _flagspecs.size(); i++) {
692                flagspec &o = _flagspecs[i];
693                if (!o.islong && c == o.name[0])
694                  return &_flagspecs[i];
695              }
696              return 0;
697            }
698            
699            const flagspec *
700            getoopt::getFlagspec(char c) {
701              return (const flagspec *)getFlagspecForUpdate(c);
702            }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2