1 //
2 // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
3 // Creation Date: Sun Apr 5 13:07:18 PDT 1998
4 // Last Modified: Sat Apr 21 10:52:19 PDT 2018 Removed using namespace std;
5 // Filename: midifile/src/Options.cpp
6 // Web Address: http://midifile.sapp.org
7 // Syntax: C++11
8 // vim: ts=3 noexpandtab
9 //
10 // Description: Interface to command-line options.
11 //
12
13 #include "Options.h"
14
15 #include <stdlib.h>
16 #include <string>
17 #include <vector>
18 #include <cctype>
19 #include <iostream>
20 #include <algorithm>
21
22
23 namespace smf {
24
25 ///////////////////////////////////////////////////////////////////////////
26 //
27 // Option_register class function definitions.
28 //
29
30
31 //////////////////////////////
32 //
33 // Option_register::Option_register -- Constructor.
34 //
35
Option_register(void)36 Option_register::Option_register(void) {
37 type = 's';
38 modifiedQ = 0;
39 }
40
41
Option_register(const std::string & aDefinition,char aType,const std::string & aDefaultOption)42 Option_register::Option_register(const std::string& aDefinition, char aType,
43 const std::string& aDefaultOption) {
44 type = 's';
45 modifiedQ = 0;
46 setType(aType);
47 setDefinition(aDefinition);
48 setDefault(aDefaultOption);
49 }
50
Option_register(const std::string & aDefinition,char aType,const std::string & aDefaultOption,const std::string & aModifiedOption)51 Option_register::Option_register(const std::string& aDefinition, char aType,
52 const std::string& aDefaultOption, const std::string& aModifiedOption) {
53 type = 's';
54 modifiedQ = 0;
55 setType(aType);
56 setDefinition(aDefinition);
57 setDefault(aDefaultOption);
58 setModified(aModifiedOption);
59 }
60
61
62
63 //////////////////////////////
64 //
65 // Option_register::~Option_register -- Destructor.
66 //
67
~Option_register()68 Option_register::~Option_register() {
69 // do nothing
70 }
71
72
73
74 //////////////////////////////
75 //
76 // Option_register::clearModified -- Clear any changes in the option value.
77 //
78
clearModified(void)79 void Option_register::clearModified(void) {
80 modifiedOption.clear();
81 modifiedQ = 0;
82 }
83
84
85
86 //////////////////////////////
87 //
88 // Option_register::getDefinition -- Returns the initial definition.
89 // string used to define this entry.
90 //
91
getDefinition(void)92 const std::string& Option_register::getDefinition(void) {
93 return definition;
94 }
95
96
97
98 //////////////////////////////
99 //
100 // Option_register::getDescription -- Return the textual description
101 // of the entry.
102 //
103
getDescription(void)104 const std::string& Option_register::getDescription(void) {
105 return description;
106 }
107
108
109
110 //////////////////////////////
111 //
112 // Option_register::getDefault -- Return the default value string.
113 //
114
getDefault(void)115 const std::string& Option_register::getDefault(void) {
116 return defaultOption;
117 }
118
119
120
121 //////////////////////////////
122 //
123 // Option_register::getModified -- Return the modified option string.
124 //
125
getModified(void)126 const std::string& Option_register::getModified(void) {
127 return modifiedOption;
128 }
129
130
131
132 //////////////////////////////
133 //
134 // Option_register::isModified -- Return true if option has been
135 // set on the command-line.
136 //
137
isModified(void)138 bool Option_register::isModified(void) {
139 return modifiedQ;
140 }
141
142
143
144 //////////////////////////////
145 //
146 // Option_register::getType -- Return the data type of the option.
147 //
148
getType(void)149 char Option_register::getType(void) {
150 return type;
151 }
152
153
154
155 //////////////////////////////
156 //
157 // Option_register::getOption -- return the modified option
158 // or the default option if no modified option.
159 //
160
getOption(void)161 const std::string& Option_register::getOption(void) {
162 if (isModified()) {
163 return getModified();
164 } else {
165 return getDefault();
166 }
167 }
168
169
170
171 //////////////////////////////
172 //
173 // Option_register::reset -- deallocate space for all
174 // strings in object. (but default string is set to "")
175 //
176
reset(void)177 void Option_register::reset(void) {
178 definition.clear();
179 defaultOption.clear();
180 modifiedOption.clear();
181 }
182
183
184
185 //////////////////////////////
186 //
187 // Option_register::setDefault -- Set the default value.
188 //
189
setDefault(const std::string & aString)190 void Option_register::setDefault(const std::string& aString) {
191 defaultOption = aString;
192 }
193
194
195
196 //////////////////////////////
197 //
198 // Option_register::setDefinition -- Set the option definition.
199 //
200
setDefinition(const std::string & aString)201 void Option_register::setDefinition(const std::string& aString) {
202 definition = aString;
203 }
204
205
206
207 //////////////////////////////
208 //
209 // Option_register::setDescription -- Set the textual description.
210 //
211
setDescription(const std::string & aString)212 void Option_register::setDescription(const std::string& aString) {
213 description = aString;
214 }
215
216
217
218 //////////////////////////////
219 //
220 // Option_register::setModified -- Set the modified value.
221 //
222
setModified(const std::string & aString)223 void Option_register::setModified(const std::string& aString) {
224 modifiedOption = aString;
225 modifiedQ = 1;
226 }
227
228
229
230 //////////////////////////////
231 //
232 // Option_register::setType -- Set the option type.
233 //
234
setType(char aType)235 void Option_register::setType(char aType) {
236 type = aType;
237 }
238
239
240
241 //////////////////////////////
242 //
243 // Option_register::print -- Print the state of the option registery entry.
244 // Useul for debugging.
245 //
246
print(std::ostream & out)247 std::ostream& Option_register::print(std::ostream& out) {
248 out << "definition:\t" << definition << std::endl;
249 out << "description:\t" << description << std::endl;
250 out << "defaultOption:\t" << defaultOption << std::endl;
251 out << "modifiedOption:\t" << modifiedOption << std::endl;
252 out << "modifiedQ:\t\t" << modifiedQ << std::endl;
253 out << "type:\t\t" << type << std::endl;
254 return out;
255 };
256
257
258
259
260 ///////////////////////////////////////////////////////////////////////////
261 //
262 // Options class function definitions.
263 //
264
265 //////////////////////////////
266 //
267 // Options::Options -- Constructor.
268 //
269
Options(void)270 Options::Options(void) {
271 m_oargc = -1;
272 m_suppressQ = 0;
273 m_processedQ = 0;
274 m_optionsArgument = 0;
275 m_options_error_check = 1;
276 m_optionFlag = '-';
277
278 m_extraArgv.reserve(100);
279 m_extraArgv_strings.reserve(100);
280 }
281
282
Options(int argc,char ** argv)283 Options::Options(int argc, char** argv) {
284 m_oargc = -1;
285 m_suppressQ = 0;
286 m_processedQ = 0;
287 m_optionsArgument = 0;
288 m_options_error_check = 1;
289 m_optionFlag = '-';
290
291 m_extraArgv.reserve(100);
292 m_extraArgv_strings.reserve(100);
293
294 setOptions(argc, argv);
295 }
296
297
298
299 //////////////////////////////
300 //
301 // Options::~Options -- Destructor.
302 //
303
~Options()304 Options::~Options() {
305 reset();
306 }
307
308
309
310 //////////////////////////////
311 //
312 // Options::argc -- returns the argument count as input from main().
313 //
314
argc(void) const315 int Options::argc(void) const {
316 return m_oargc;
317 }
318
319
320
321 //////////////////////////////
322 //
323 // Options::argv -- returns the arguments strings as input from main().
324 //
325
argv(void) const326 const std::vector<std::string>& Options::argv(void) const {
327 return m_oargv;
328 }
329
330
331
332 //////////////////////////////
333 //
334 // Options::define -- store an option definition in the registry. Option
335 // definitions have this sructure:
336 // option-name|alias-name1|alias-name2=option-type:option-default
337 // option-name :: name of the option (one or more character, not including
338 // spaces or equal signs.
339 // alias-name :: equivalent name(s) of the option.
340 // option-type :: single charater indicating the option data type.
341 // option-default :: default value for option if no given on the command-line.
342 //
343
define(const std::string & aDefinition)344 int Options::define(const std::string& aDefinition) {
345 Option_register* definitionEntry = NULL;
346
347 // Error if definition string doesn't contain an equals sign
348 auto location = aDefinition.find("=");
349 if (location == std::string::npos) {
350 std::cerr << "Error: no \"=\" in option definition: " << aDefinition << std::endl;
351 exit(1);
352 }
353
354 std::string aliases = aDefinition.substr(0, location);
355 std::string rest = aDefinition.substr(location+1);
356 std::string otype = rest;
357 std::string ovalue = "";
358
359 location = rest.find(":");
360 if (location != std::string::npos) {
361 otype = rest.substr(0, location);
362 ovalue = rest.substr(location+1);
363 }
364
365 // Remove anyspaces in the option type field
366 otype.erase(remove_if(otype.begin(), otype.end(), ::isspace), otype.end());
367
368 // Option types are only a single charater (b, i, d, c or s)
369 if (otype.size() != 1) {
370 std::cerr << "Error: option type is invalid: " << otype
371 << " in option definition: " << aDefinition << std::endl;
372 exit(1);
373 }
374
375 // Check to make sure that the type is known
376 if (otype[0] != OPTION_STRING_TYPE &&
377 otype[0] != OPTION_INT_TYPE &&
378 otype[0] != OPTION_FLOAT_TYPE &&
379 otype[0] != OPTION_DOUBLE_TYPE &&
380 otype[0] != OPTION_BOOLEAN_TYPE &&
381 otype[0] != OPTION_CHAR_TYPE ) {
382 std::cerr << "Error: unknown option type \'" << otype[0]
383 << "\' in defintion: " << aDefinition << std::endl;
384 exit(1);
385 }
386
387 // Set up space for a option entry in the registry
388 definitionEntry = new Option_register(aDefinition, otype[0], ovalue);
389
390 int definitionIndex = (int)m_optionRegister.size();
391
392 // Store option aliases
393 std::string optionName;
394 unsigned int i;
395 aliases += '|';
396 for (i=0; i<aliases.size(); i++) {
397 if (::isspace(aliases[i])) {
398 continue;
399 } else if (aliases[i] == '|') {
400 if (isDefined(optionName)) {
401 std::cerr << "Option \"" << optionName << "\" from definition:" << std::endl;
402 std::cerr << "\t" << aDefinition << std::endl;
403 std::cerr << "is already defined in: " << std::endl;
404 std::cerr << "\t" << getDefinition(optionName) << std::endl;
405 exit(1);
406 }
407 if (optionName.size() > 0) {
408 m_optionList[optionName] = definitionIndex;
409 }
410 optionName.clear();
411 } else {
412 optionName += aliases[i];
413 }
414 }
415
416 // Store definition in registry and return its indexed location.
417 // This location will be used to link option aliases to the main
418 // command name.
419 m_optionRegister.push_back(definitionEntry);
420 return definitionIndex;
421 }
422
423
define(const std::string & aDefinition,const std::string & aDescription)424 int Options::define(const std::string& aDefinition,
425 const std::string& aDescription) {
426 int index = define(aDefinition);
427 m_optionRegister[index]->setDescription(aDescription);
428 return index;
429 }
430
431
432
433 //////////////////////////////
434 //
435 // Options::isDefined -- Return true if option is present in registry.
436 //
437
isDefined(const std::string & name)438 bool Options::isDefined(const std::string& name) {
439 return m_optionList.find(name) == m_optionList.end() ? false : true;
440 }
441
442
443
444 //////////////////////////////
445 //
446 // Options::getArg -- returns the specified argument.
447 // argurment 0 is the command name.
448 //
449
getArg(int index)450 const std::string& Options::getArg(int index) {
451 if (index < 0 || index >= (int)m_argument.size()) {
452 std::cerr << "Error: m_argument " << index << " does not exist." << std::endl;
453 exit(1);
454 }
455 return m_argument[index];
456 }
457
458 // Alias:
459
getArgument(int index)460 const std::string& Options::getArgument(int index) {
461 return getArg(index);
462 }
463
464
465
466 //////////////////////////////
467 //
468 // Options::getArgCount -- number of arguments on command line.
469 // does not count the options or the command name.
470 //
471
getArgCount(void)472 int Options::getArgCount(void) {
473 return ((int)m_argument.size()) - 1;
474 }
475
476 // Alias:
477
getArgumentCount(void)478 int Options::getArgumentCount(void) {
479 return getArgCount();
480 }
481
482
483
484 //////////////////////////////
485 //
486 // Options::getArgList -- return a string vector of the arguments
487 // after the options have been parsed out of it.
488 //
489
getArgList(void)490 const std::vector<std::string>& Options::getArgList(void) {
491 return m_argument;
492 }
493
494 // Alias:
495
getArgumentList(void)496 const std::vector<std::string>& Options::getArgumentList(void) {
497 return getArgList();
498 }
499
500
501
502 //////////////////////////////
503 //
504 // Options::getBoolean -- returns true if the option was
505 // used on the command line.
506 //
507
getBoolean(const std::string & optionName)508 bool Options::getBoolean(const std::string& optionName) {
509 int index = getRegIndex(optionName);
510 if (index < 0) {
511 return 0;
512 }
513 return m_optionRegister[index]->isModified();
514 }
515
516
517
518 //////////////////////////////
519 //
520 // Options::getCommand -- returns argv[0] (the first string
521 // in the original argv list.
522 //
523
getCommand(void)524 std::string Options::getCommand(void) {
525 if (m_argument.size() == 0) {
526 return "";
527 } else {
528 return m_argument[0];
529 }
530 }
531
532
533
534 //////////////////////////////
535 //
536 // Options::getCommandLine -- returns a string which contains the
537 // command-line call to the program. Deal with spaces in arguments...
538 //
539
getCommandLine(void)540 const std::string& Options::getCommandLine(void) {
541 if (m_commandString.size()) {
542 return m_commandString;
543 }
544
545 m_commandString = m_oargv[0];
546
547 int i;
548 for (i=1; i<m_oargc; i++) {
549 m_commandString += " ";
550 m_commandString += m_oargv[i];
551 }
552
553 return m_commandString;
554 }
555
556
557
558
559 //////////////////////////////
560 //
561 // Options::getDefinition -- returns the definition for the specified
562 // option name. Returns empty string if there is no entry for
563 // the option name. spaces count in the input option name.
564 //
565
getDefinition(const std::string & optionName)566 std::string Options::getDefinition(const std::string& optionName) {
567 auto it = m_optionList.find(optionName);
568 if (it == m_optionList.end()) {
569 return "";
570 } else {
571 return m_optionRegister[it->second]->getDefinition();
572 }
573 }
574
575
576
577 //////////////////////////////
578 //
579 // Options::getDouble -- returns the double float associated
580 // with the given option. Returns 0 if there is no
581 // number associated with the option.
582 //
583
getDouble(const std::string & optionName)584 double Options::getDouble(const std::string& optionName) {
585 return strtod(getString(optionName).c_str(), (char**)NULL);
586 }
587
588
589
590 //////////////////////////////
591 //
592 // Options::getChar -- Return the first character in the option string;
593 // If the length is zero, then return '\0'.
594 //
595
getChar(const std::string & optionName)596 char Options::getChar(const std::string& optionName) {
597 return getString(optionName).c_str()[0];
598 }
599
600
601
602 //////////////////////////////
603 //
604 // Options::getFloat -- Return the floating point number
605 // associated with the given option.
606 //
607
getFloat(const std::string & optionName)608 float Options::getFloat(const std::string& optionName) {
609 return (float)getDouble(optionName);
610 }
611
612
613
614 //////////////////////////////
615 //
616 // Options::getInt -- Return the integer argument. Can handle
617 // hexadecimal, decimal, and octal written in standard
618 // C syntax.
619 //
620
getInt(const std::string & optionName)621 int Options::getInt(const std::string& optionName) {
622 return (int)strtol(getString(optionName).c_str(), (char**)NULL, 0);
623 }
624
getInteger(const std::string & optionName)625 int Options::getInteger(const std::string& optionName) {
626 return getInt(optionName);
627 }
628
629
630
631 //////////////////////////////
632 //
633 // Options::getString -- Return the option argument string.
634 //
635
getString(const std::string & optionName)636 std::string Options::getString(const std::string& optionName) {
637 int index = getRegIndex(optionName);
638 if (index < 0) {
639 return "UNKNOWN OPTION";
640 } else {
641 return m_optionRegister[index]->getOption();
642 }
643 }
644
645
646
647 //////////////////////////////
648 //
649 // Options::optionsArg -- Return true if --options is present
650 // on the command line, otherwise returns false.
651 //
652
optionsArg(void)653 int Options::optionsArg(void) {
654 return m_optionsArgument;
655 }
656
657
658
659 //////////////////////////////
660 //
661 // Options::print -- Print a list of the defined options.
662 //
663
print(std::ostream & out)664 std::ostream& Options::print(std::ostream& out) {
665 for (unsigned int i=0; i<m_optionRegister.size(); i++) {
666 out << m_optionRegister[i]->getDefinition() << "\t"
667 << m_optionRegister[i]->getDescription() << std::endl;
668 }
669 return out;
670 }
671
672
673
674 //////////////////////////////
675 //
676 // Options::reset -- Clear all defined options.
677 //
678
reset(void)679 void Options::reset(void) {
680 unsigned int i;
681 for (i=0; i<m_optionRegister.size(); i++) {
682 delete m_optionRegister[i];
683 m_optionRegister[i] = NULL;
684 }
685 m_optionRegister.clear();
686
687 m_argument.clear();
688 m_commandString.clear();
689 m_extraArgv.clear();
690 m_extraArgv_strings.clear();
691
692 m_oargc = -1;
693 m_oargv.clear();
694 }
695
696
697
698 //////////////////////////////
699 //
700 // Options::getFlag -- Set the character which is usually set to a dash.
701 //
702
getFlag(void)703 char Options::getFlag(void) {
704 return m_optionFlag;
705 }
706
707
708
709 //////////////////////////////
710 //
711 // Options::setFlag -- Set the character used to indicate an
712 // option. For unix this is usually '-', in MS-DOS,
713 // this is usually '/'; But the syntax of the Options
714 // class is for Unix-style options.
715 //
716
setFlag(char aFlag)717 void Options::setFlag(char aFlag) {
718 m_optionFlag = aFlag;
719 }
720
721
722
723 //////////////////////////////
724 //
725 // Options::setModified --
726 //
727
setModified(const std::string & optionName,const std::string & aString)728 void Options::setModified(const std::string& optionName,
729 const std::string& aString) {
730 int index = getRegIndex(optionName);
731 if (index < 0) {
732 return;
733 }
734
735 m_optionRegister[getRegIndex(optionName)]->setModified(aString);
736 }
737
738
739
740
741 //////////////////////////////
742 //
743 // Options::setOptions -- Store the input list of options.
744 //
745
setOptions(int argc,char ** argv)746 void Options::setOptions(int argc, char** argv) {
747 m_processedQ = 0;
748
749 m_extraArgv.resize(argc);
750 m_extraArgv_strings.resize(argc);
751 int oldsize = 0;
752
753 int i;
754 for (i=0; i<argc; i++) {
755 m_extraArgv_strings[i+oldsize] = argv[i];
756 m_extraArgv[i] = m_extraArgv_strings[i];
757 }
758
759 m_oargc = (int)m_extraArgv.size();
760 m_oargv = m_extraArgv;
761 }
762
763
764
765 //////////////////////////////
766 //
767 // Options::appendOptions -- Add argc and argv data to the current
768 // list residing inside the Options class variable.
769 //
770
appendOptions(int argc,char ** argv)771 void Options::appendOptions(int argc, char** argv) {
772 m_processedQ = 0;
773
774 // data used to be stored directly here:
775 //gargc = argc;
776 //gargv = argv;
777 // but now gets interfaced to: m_extraArgv and m_extraArgv_strings:
778
779 int oldsize = (int)m_extraArgv.size();
780 m_extraArgv.resize(oldsize + argc);
781 m_extraArgv_strings.resize(oldsize + argc);
782
783 int i;
784 for (i=0; i<argc; i++) {
785 m_extraArgv_strings[i+oldsize] = argv[i];
786 m_extraArgv[i+oldsize] = m_extraArgv_strings[i+oldsize];
787 }
788
789 m_oargc = (int)m_extraArgv.size();
790 m_oargv = m_extraArgv;
791 }
792
793
appendOptions(const std::vector<std::string> & argv)794 void Options::appendOptions(const std::vector<std::string>& argv) {
795 m_processedQ = 0;
796
797 int oldsize = (int)m_extraArgv.size();
798 m_extraArgv.resize(oldsize + argv.size());
799 m_extraArgv_strings.resize(oldsize + argv.size());
800
801 unsigned int i;
802 for (i=0; i<argv.size(); i++) {
803 m_extraArgv_strings[i+oldsize] = argv[i];
804 m_extraArgv[i+oldsize] = m_extraArgv_strings[i+oldsize];
805 }
806
807 m_oargc = (int)m_extraArgv.size();
808 m_oargv = m_extraArgv;
809 }
810
811
812
813 //////////////////////////////
814 //
815 // Options::appendOptions -- parse the string like command-line arguments.
816 // Either double or single quotes can be used to encapsulate
817 // a command-line token. If double quotes are used to encapsulate,
818 // then you will not have to back quote single quotes inside the
819 // token string, but you will have to backslash double quotes:
820 // "-T \"\"" but "-T ''"
821 // Likewise for single quotes in reverse with double quotes:
822 // '-T \'\'' is equal to: '-T ""'
823 //
824
appendOptions(const std::string & strang)825 void Options::appendOptions(const std::string& strang) {
826 int i;
827 int doublequote = 0;
828 int singlequote = 0;
829
830 std::vector<std::string> tokens;
831 std::vector<std::string> tempargv;
832 std::string tempvalue;
833
834 tokens.reserve(100);
835 tempargv.reserve(100);
836 tempvalue.reserve(1000);
837
838 char ch;
839
840 int length = (int)strang.size();
841 for (i=0; i<length; i++) {
842
843 if (!singlequote && (strang[i] == '"')) {
844 if ((i>0) && (strang[i-1] != '\\')) {
845 doublequote = !doublequote;
846 if (doublequote == 0) {
847 // finished a doublequoted section of data, so store
848 // even if it is the empty string
849 ch = '\0';
850 tempvalue += (ch);
851 tokens.push_back(tempvalue);
852 tempvalue.clear();
853 continue;
854 } else {
855 // don't store the leading ":
856 continue;
857 }
858 }
859 } else if (!doublequote && (strang[i] == '\'')) {
860 if ((i>0) && (strang[i-1] != '\\')) {
861 singlequote = !singlequote;
862 if (singlequote == 0) {
863 // finished a singlequote section of data, so store
864 // even if it is the empty string
865 ch = '\0';
866 tempvalue += ch;
867 tokens.push_back(tempvalue);
868 tempvalue.clear();
869 continue;
870 } else {
871 // don't store the leading ":
872 continue;
873 }
874 }
875 }
876
877
878 if ((!doublequote && !singlequote) && std::isspace(strang[i])) {
879 if (tempvalue.size() > 0) {
880 tempvalue += ch;
881 tokens.push_back(tempvalue);
882 tempvalue.clear();
883 }
884 } else {
885 ch = strang[i];
886 tempvalue += ch;
887 }
888 }
889 if (tempvalue.size() > 0) {
890 tokens.push_back(tempvalue);
891 tempvalue.clear();
892 }
893
894 // now that the input string has been chopped up into pieces,
895 // assemble the argv structure
896
897 tempargv.reserve(tokens.size());
898 for (i=0; i<(int)tempargv.size(); i++) {
899 tempargv[i] = tokens[i];
900 }
901
902 // now store the argv and argc data in opts:
903
904 // now store the parsed command-line simulated tokens
905 // for actual storage:
906 appendOptions(tempargv);
907 }
908
909
910
911 //////////////////////////////
912 //
913 // Options:getType -- Return the type of the option.
914 //
915
getType(const std::string & optionName)916 char Options::getType(const std::string& optionName) {
917 int index = getRegIndex(optionName);
918 if (index < 0) {
919 return -1;
920 } else {
921 return m_optionRegister[getRegIndex(optionName)]->getType();
922 }
923 }
924
925
926
927 //////////////////////////////
928 //
929 // Options::process -- Same as xverify.
930 // default values: error_check = 1, suppress = 0;
931 //
932
process(int argc,char ** argv,int error_check,int suppress)933 void Options::process(int argc, char** argv, int error_check, int suppress) {
934 setOptions(argc, argv);
935 xverify(error_check, suppress);
936 }
937
938
process(int error_check,int suppress)939 void Options::process(int error_check, int suppress) {
940 xverify(error_check, suppress);
941 }
942
943
944
945 //////////////////////////////
946 //
947 // Options::xverify --
948 // default value: error_check = 1, suppress = 0;
949 //
950
xverify(int error_check,int suppress)951 void Options::xverify(int error_check, int suppress) {
952 m_options_error_check = error_check;
953 int gargp = 1;
954 int optionend = 0;
955
956 if (suppress) {
957 m_suppressQ = 1;
958 } else {
959 m_suppressQ = 0;
960 }
961
962 // if calling xverify again, must remove previous argument list.
963 if (m_argument.size() != 0) {
964 m_argument.clear();
965 }
966
967 m_argument.push_back(m_oargv[0]);
968 int oldgargp;
969 int position = 0;
970 int running = 0;
971 while (gargp < m_oargc && optionend == 0) {
972 if (optionQ(m_oargv[gargp], gargp)) {
973 oldgargp = gargp;
974 gargp = storeOption(gargp, position, running);
975 if (gargp != oldgargp) {
976 running = 0;
977 position = 0;
978 }
979 } else {
980 if (m_oargv[gargp].size() == 2 && m_oargv[gargp][0] == getFlag() &&
981 m_oargv[gargp][2] == getFlag() ) {
982 optionend = 1;
983 gargp++;
984 break;
985 } else { // this is an argument
986 m_argument.push_back(m_oargv[gargp]);
987 gargp++;
988 }
989 }
990 }
991
992 while (gargp < m_oargc) {
993 m_argument.push_back(m_oargv[gargp]);
994 gargp++;
995 }
996
997 }
998
999
xverify(int argc,char ** argv,int error_check,int suppress)1000 void Options::xverify(int argc, char** argv, int error_check, int suppress) {
1001 setOptions(argc, argv);
1002 xverify(error_check, suppress);
1003 }
1004
1005
1006
1007
1008 ///////////////////////////////////////////////////////////////////////////
1009 //
1010 // private functions
1011 //
1012
1013
1014 //////////////////////////////
1015 //
1016 // Options::getRegIndex -- returns the index of the option associated
1017 // with this name.
1018 //
1019
getRegIndex(const std::string & optionName)1020 int Options::getRegIndex(const std::string& optionName) {
1021 if (m_suppressQ && (optionName == "options")) {
1022 return -1;
1023 }
1024
1025 if (optionName == "options") {
1026 print(std::cout);
1027 exit(0);
1028 }
1029
1030
1031 auto it = m_optionList.find(optionName);
1032 if (it == m_optionList.end()) {
1033 if (m_options_error_check) {
1034 std::cerr << "Error: unknown option \"" << optionName << "\"." << std::endl;
1035 print(std::cout);
1036 exit(1);
1037 } else {
1038 return -1;
1039 }
1040 } else {
1041 return it->second;
1042 }
1043 }
1044
1045
1046
1047 //////////////////////////////
1048 //
1049 // Options::optionQ -- returns true if the string is an option
1050 // "--" is not an option, also '-' is not an option.
1051 // aString is assumed to not be NULL.
1052 //
1053
optionQ(const std::string & aString,int & argp)1054 int Options::optionQ(const std::string& aString, int& argp) {
1055 if (aString[0] == getFlag()) {
1056 if (aString[1] == '\0') {
1057 argp++;
1058 return 0;
1059 } else if (aString[1] == getFlag()) {
1060 if (aString[2] == '\0') {
1061 argp++;
1062 return 0;
1063 } else {
1064 return 1;
1065 }
1066 } else {
1067 return 1;
1068 }
1069 } else {
1070 return 0;
1071 }
1072 }
1073
1074
1075
1076 //////////////////////////////
1077 //
1078 // Options::storeOption --
1079 //
1080
1081 #define OPTION_FORM_SHORT 0
1082 #define OPTION_FORM_LONG 1
1083 #define OPTION_FORM_CONTINUE 2
1084
storeOption(int gargp,int & position,int & running)1085 int Options::storeOption(int gargp, int& position, int& running) {
1086 int optionForm;
1087 char tempname[1024];
1088 char optionType = '\0';
1089
1090 if (running) {
1091 optionForm = OPTION_FORM_CONTINUE;
1092 } else if (m_oargv[gargp][1] == getFlag()) {
1093 optionForm = OPTION_FORM_LONG;
1094 } else {
1095 optionForm = OPTION_FORM_SHORT;
1096 }
1097
1098 switch (optionForm) {
1099 case OPTION_FORM_CONTINUE:
1100 position++;
1101 tempname[0] = m_oargv[gargp][position];
1102 tempname[1] = '\0';
1103 optionType = getType(tempname);
1104 if (optionType != OPTION_BOOLEAN_TYPE) {
1105 running = 0;
1106 position++;
1107 }
1108 break;
1109 case OPTION_FORM_SHORT:
1110 position = 1;
1111 tempname[0] = m_oargv[gargp][position];
1112 tempname[1] = '\0';
1113 optionType = getType(tempname);
1114 if (optionType != OPTION_BOOLEAN_TYPE) {
1115 position++;
1116 }
1117 break;
1118 case OPTION_FORM_LONG:
1119 position = 2;
1120 while (m_oargv[gargp][position] != '=' &&
1121 m_oargv[gargp][position] != '\0') {
1122 tempname[position-2] = m_oargv[gargp][position];
1123 position++;
1124 }
1125 tempname[position-2] = '\0';
1126 optionType = getType(tempname);
1127 if (optionType == -1) { // suppressed --options option
1128 m_optionsArgument = 1;
1129 break;
1130 }
1131 if (m_oargv[gargp][position] == '=') {
1132 if (optionType == OPTION_BOOLEAN_TYPE) {
1133 std::cerr << "Error: boolean variable cannot have any options: "
1134 << tempname << std::endl;
1135 exit(1);
1136 }
1137 position++;
1138 }
1139 break;
1140 }
1141
1142 if (optionType == -1) { // suppressed --options option
1143 m_optionsArgument = 1;
1144 gargp++;
1145 position = 0;
1146 return gargp;
1147 }
1148
1149 if (m_oargv[gargp][position] == '\0' &&
1150 optionType != OPTION_BOOLEAN_TYPE) {
1151 gargp++;
1152 position = 0;
1153 }
1154
1155 if (optionForm != OPTION_FORM_LONG && optionType == OPTION_BOOLEAN_TYPE &&
1156 m_oargv[gargp][position+1] != '\0') {
1157 running = 1;
1158 } else if (optionType == OPTION_BOOLEAN_TYPE &&
1159 m_oargv[gargp][position+1] == '\0') {
1160 running = 0;
1161 }
1162
1163 if (gargp >= m_oargc) {
1164 std::cerr << "Error: last option requires a parameter" << std::endl;
1165 exit(1);
1166 }
1167 setModified(tempname, &m_oargv[gargp][position]);
1168
1169 if (!running) {
1170 gargp++;
1171 }
1172 return gargp;
1173 }
1174
1175
1176
1177 //////////////////////////////
1178 //
1179 // Options::printOptionList --
1180 //
1181
printOptionList(std::ostream & out)1182 std::ostream& Options::printOptionList(std::ostream& out) {
1183 for (auto it = m_optionList.begin(); it != m_optionList.end(); it++) {
1184 out << it->first << "\t" << it->second << std::endl;
1185 }
1186 return out;
1187 }
1188
1189
1190
1191 //////////////////////////////
1192 //
1193 // Options::printOptionBooleanState --
1194 //
1195
printOptionListBooleanState(std::ostream & out)1196 std::ostream& Options::printOptionListBooleanState(std::ostream& out) {
1197 for (auto it = m_optionList.begin(); it != m_optionList.end(); it++) {
1198 out << it->first << "\t"
1199 << m_optionRegister[it->second]->isModified() << std::endl;
1200 }
1201 return out;
1202 }
1203
1204
1205
1206 //////////////////////////////
1207 //
1208 // Options::printRegister --
1209 //
1210
printRegister(std::ostream & out)1211 std::ostream& Options::printRegister(std::ostream& out) {
1212 for (auto it = m_optionRegister.begin(); it != m_optionRegister.end(); it++) {
1213 (*it)->print(out);
1214 }
1215 return out;
1216 }
1217
1218
1219 } // end namespace smf
1220
1221
1222
1223