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