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