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 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 using
535 // getoopt::const_iterator
536 //-----------------------------------------------
537
538 Optarg *
539 getoopt::begin() {
540 return _args.begin();
541 }
542 mike 1.13
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 // 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 mike 1.13 }
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 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 mike 1.13 // 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 } 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 mike 1.13 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 }
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 mike 1.13 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 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 mike 1.13 // 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
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 mike 1.13 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 }
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 mike 1.13 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 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 mike 1.13 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 getoopt::getFlagspec(char c) {
722 return (const flagspec *)getFlagspecForUpdate(c);
723 }
|