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 }
|