1 /*
2 * Medical Image Registration ToolKit (MIRTK)
3 *
4 * Copyright 2013-2016 Imperial College London
5 * Copyright 2013-2016 Andreas Schuh
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include "mirtk/Options.h"
21
22 #include "mirtk/String.h"
23 #include "mirtk/Stream.h"
24 #include "mirtk/Version.h" // PrintVersion/PrintRevision
25 #include "mirtk/Terminal.h" // PrintTerminalOptions
26 #include "mirtk/Parallel.h" // PrintParallelOptions
27 #include "mirtk/Profiling.h" // PrintProfilingOptions
28
29 #include "mirtk/CommonExport.h"
30
31
32 namespace mirtk {
33
34
35 // =============================================================================
36 // Global standard options
37 // =============================================================================
38
39 // Default: No verbose output messages
40 MIRTK_Common_EXPORT int verbose = 0;
41
42 // Default: No debug output
43 MIRTK_Common_EXPORT int debug = 0;
44
45 // =============================================================================
46 // Help
47 // =============================================================================
48
49 MIRTK_Common_EXPORT int _posargc = 0;
50 MIRTK_Common_EXPORT int _numposarg = -1;
51 MIRTK_Common_EXPORT bool _discard_parsed_posargs = false;
52 MIRTK_Common_EXPORT bool _discard_parsed_options = false;
53 MIRTK_Common_EXPORT const char *_option = NULL;
54
55 // -----------------------------------------------------------------------------
IsStandardOption(const char * arg)56 bool IsStandardOption(const char *arg)
57 {
58 _option = NULL;
59 if (strcmp(arg, "-v") == 0) _option = "-v";
60 else if (strcmp(arg, "-verbose") == 0) _option = "-verbose";
61 else if (strcmp(arg, "-debug") == 0) _option = "-debug";
62 else if (strcmp(arg, "-revision") == 0) _option = "-revision";
63 else if (strcmp(arg, "-version") == 0 || strcmp(arg, "--version") == 0) _option = "-version";
64 return (_option != NULL);
65 }
66
67 // -----------------------------------------------------------------------------
ParseStandardOption(int & OPTIDX,int & argc,char * argv[])68 void ParseStandardOption(int &OPTIDX, int &argc, char *argv[])
69 {
70 if (OPTION("-v") || OPTION("-verbose")) {
71 if (HAS_ARGUMENT) verbose = atoi(ARGUMENT);
72 else verbose += 1;
73 } else if (OPTION("-debug")) {
74 if (HAS_ARGUMENT) debug = atoi(ARGUMENT);
75 else debug += 1;
76 } else if (OPTION("-version") || OPTION("--version")) {
77 if (HAS_ARGUMENT) {
78 if (!FromString(ARGUMENT, version) || version > current_version) {
79 cerr << "Invalid [-]-version argument" << endl;
80 exit(1);
81 }
82 } else {
83 PrintVersion(cout, EXECNAME);
84 exit(0);
85 }
86 } else if (OPTION("-revision")) {
87 PrintRevision(cout);
88 exit(0);
89 }
90 }
91
92 // -----------------------------------------------------------------------------
PrintStandardOptions(ostream & out)93 void PrintStandardOptions(ostream &out)
94 {
95 out << endl;
96 out << "Standard options:" << endl;
97 out << " -v, -verbose [n] Increase/Set verbosity of output messages. (default: " << verbose << ")" << endl;
98 out << " -debug [level] Increase/Set debug level for output of intermediate results. (default: " << debug << ")" << endl;
99 out << " -[-]version [major.minor] Print version and exit or set version to emulate." << endl;
100 out << " -revision Print revision (or version) number only and exit." << endl;
101 out << " -h, -[-]help Print help and exit." << endl;
102 }
103
104 // -----------------------------------------------------------------------------
PrintCommonOptions(ostream & out)105 void PrintCommonOptions(ostream &out)
106 {
107 PrintStandardOptions (out);
108 PrintTerminalOptions (out);
109 PrintParallelOptions (out);
110 PrintProfilingOptions(out);
111 }
112
113 // =============================================================================
114 // Private functions used by command-line parsing macros
115 // =============================================================================
116
117 // -----------------------------------------------------------------------------
_IsOptionName(const char * arg)118 inline bool _IsOptionName(const char *arg)
119 {
120 return arg[0] == '-' && (arg[1] == '-' || !IsNumber(arg));
121 }
122
123 // -----------------------------------------------------------------------------
_GetNumberOfPositionalArguments(int argc,char * argv[])124 int _GetNumberOfPositionalArguments(int argc, char *argv[])
125 {
126 int n = 1;
127 while (n < argc && !_IsOptionName(argv[n])) n++;
128 return n - 1;
129 }
130
131 // -----------------------------------------------------------------------------
_DiscardArgument(int & i,int & argc,char * argv[])132 void _DiscardArgument(int &i, int &argc, char *argv[])
133 {
134 for (int j = i; j < argc; j++) argv[j] = argv[j+1];
135 argv[argc--] = NULL;
136 i--;
137 }
138
139 // -----------------------------------------------------------------------------
_IsOption(int & i,int & argc,char * argv[],const char * opt)140 bool _IsOption(int &i, int &argc, char *argv[], const char *opt)
141 {
142 if ((opt == NULL && _IsOptionName(argv[i])) || (opt != NULL && strcmp(argv[i], opt) == 0)) {
143 if (_discard_parsed_options) _DiscardArgument(i, argc, argv);
144 _option = argv[i];
145 return true;
146 } else {
147 _option = NULL;
148 return false;
149 }
150 }
151
152 // -----------------------------------------------------------------------------
_IsArgument(int i,int & argc,char * argv[])153 bool _IsArgument(int i, int &argc, char *argv[])
154 {
155 return (i+1 < argc && !_IsOptionName(argv[i+1]));
156 }
157
158 // -----------------------------------------------------------------------------
_GetPositionalArgument(int i,int & argc,char * argv[])159 char *_GetPositionalArgument(int i, int &argc, char *argv[])
160 {
161 if (i >= argc) {
162 cerr << "Error: Not all required arguments specified!" << endl;
163 exit(1);
164 }
165 if (_posargc < i) _posargc = i;
166 char *arg = argv[i];
167 return arg;
168 }
169
170 // -----------------------------------------------------------------------------
_GetOptionArgument(int & i,int & argc,char * argv[])171 char *_GetOptionArgument(int &i, int &argc, char *argv[])
172 {
173 if (_option) {
174 i++;
175 if (i >= argc) {
176 cerr << "Error: Option";
177 if (_option) cerr << " " << _option;
178 cerr << " requires more arguments than specified!" << endl;
179 exit(1);
180 }
181 } else {
182 if (i >= argc) {
183 cerr << "Error: Not all required arguments specified!" << endl;
184 exit(1);
185 }
186 if (_posargc < i) _posargc = i;
187 }
188 char *arg = argv[i];
189 if (_discard_parsed_options) _DiscardArgument(i, argc, argv);
190 return arg;
191 }
192
193
194 } // namespace mirtk
195