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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2