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