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