SCM Repository
Annotation of /branches/cuda/src/lib/common/options.cxx
Parent Directory
|
Revision Log
Revision 5622 - (view) (download) (as text)
1 : | jhr | 5597 | /*! \file options.cxx |
2 : | * | ||
3 : | * \author John Reppy | ||
4 : | */ | ||
5 : | |||
6 : | /* | ||
7 : | * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu) | ||
8 : | * | ||
9 : | * COPYRIGHT (c) 2016 The University of Chicago | ||
10 : | * All rights reserved. | ||
11 : | */ | ||
12 : | |||
13 : | adrianlehm | 5619 | #include "diderot/options.h" |
14 : | jhr | 5597 | |
15 : | #include <iostream> | ||
16 : | #include <sstream> | ||
17 : | #include <cstdio> | ||
18 : | #include <cstring> | ||
19 : | adrianlehm | 5622 | #include <cstdint> |
20 : | jhr | 5597 | #include <teem/air.h> |
21 : | #include <teem/hest.h> | ||
22 : | |||
23 : | namespace diderot { | ||
24 : | |||
25 : | namespace __details { | ||
26 : | |||
27 : | /*! The base struct for representing information about a single command-line option. | ||
28 : | */ | ||
29 : | struct option_base { | ||
30 : | std::string _name; //! the option name | ||
31 : | std::string _desc; //! the option description | ||
32 : | bool _hasDflt; //! true if the option has a default value | ||
33 : | void *_gv; //! pointer to the global variable being set | ||
34 : | |||
35 : | option_base (std::string const &name, std::string const &desc, void *gv, bool hasDflt) | ||
36 : | : _name(name), _desc(desc), _hasDflt(hasDflt), _gv(gv) | ||
37 : | { } | ||
38 : | |||
39 : | virtual ~option_base () { } | ||
40 : | |||
41 : | // register_opt the option with hest | ||
42 : | virtual void register_opt (hestOpt **) = 0; | ||
43 : | // copy the value specified on the command-line to the global input variable | ||
44 : | virtual void init_input () = 0; | ||
45 : | }; | ||
46 : | |||
47 : | /********** flag options **********/ | ||
48 : | |||
49 : | struct option_flag : public option_base { | ||
50 : | int _val; | ||
51 : | |||
52 : | option_flag (std::string const &name, std::string const &desc, void *gv) | ||
53 : | : option_base (name, desc, gv, false) | ||
54 : | { } | ||
55 : | ~option_flag () { } | ||
56 : | |||
57 : | bool *var () const { return reinterpret_cast<bool *>(this->_gv); } | ||
58 : | |||
59 : | void register_opt (hestOpt **); | ||
60 : | void init_input (); | ||
61 : | }; | ||
62 : | |||
63 : | void option_flag::register_opt (hestOpt **hOpt) | ||
64 : | { | ||
65 : | hestOptAdd ( | ||
66 : | hOpt, this->_name.c_str(), nullptr, airTypeInt, 0, 0, &this->_val, | ||
67 : | nullptr, this->_desc.c_str()); | ||
68 : | } | ||
69 : | |||
70 : | void option_flag::init_input () | ||
71 : | { | ||
72 : | *this->var() = (this->_val ? true : false); | ||
73 : | } | ||
74 : | |||
75 : | /********** boolean options **********/ | ||
76 : | |||
77 : | struct option_bool : public option_base { | ||
78 : | int _val; | ||
79 : | |||
80 : | option_bool (std::string const &name, std::string const &desc, bool *gv, bool hasDflt) | ||
81 : | : option_base (name, desc, gv, hasDflt) | ||
82 : | { } | ||
83 : | ~option_bool () { } | ||
84 : | |||
85 : | bool *var () const { return reinterpret_cast<bool *>(this->_gv); } | ||
86 : | |||
87 : | void register_opt (hestOpt **); | ||
88 : | void init_input (); | ||
89 : | }; | ||
90 : | |||
91 : | void option_bool::register_opt (hestOpt **hOpt) | ||
92 : | { | ||
93 : | hestOptAdd ( | ||
94 : | hOpt, this->_name.c_str(), "bool", airTypeBool, 1, 1, &this->_val, | ||
95 : | this->_hasDflt ? (*this->var() ? "true" : "false") : nullptr, | ||
96 : | this->_desc.c_str()); | ||
97 : | } | ||
98 : | |||
99 : | void option_bool::init_input () | ||
100 : | { | ||
101 : | *this->var() = (this->_val ? true : false); | ||
102 : | } | ||
103 : | |||
104 : | /********** 32-bit integer options **********/ | ||
105 : | |||
106 : | struct option_int32 : public option_base { | ||
107 : | int32_t _val; | ||
108 : | |||
109 : | option_int32 (std::string const &name, std::string const &desc, int32_t *gv, bool hasDflt) | ||
110 : | : option_base (name, desc, gv, hasDflt) | ||
111 : | { } | ||
112 : | ~option_int32 () { } | ||
113 : | |||
114 : | int32_t *var () const { return reinterpret_cast<int32_t *>(this->_gv); } | ||
115 : | |||
116 : | void register_opt (hestOpt **); | ||
117 : | void init_input (); | ||
118 : | }; | ||
119 : | |||
120 : | void option_int32::register_opt (hestOpt **hOpt) | ||
121 : | { | ||
122 : | if (this->_hasDflt) { | ||
123 : | std::ostringstream os; | ||
124 : | os << *this->var(); | ||
125 : | hestOptAdd ( | ||
126 : | hOpt, this->_name.c_str(), "int", airTypeInt, 1, 1, &this->_val, | ||
127 : | os.str().c_str(), this->_desc.c_str()); | ||
128 : | } | ||
129 : | else { | ||
130 : | hestOptAdd ( | ||
131 : | hOpt, this->_name.c_str(), "int", airTypeInt, 1, 1, &this->_val, | ||
132 : | nullptr, this->_desc.c_str()); | ||
133 : | } | ||
134 : | } | ||
135 : | |||
136 : | void option_int32::init_input () | ||
137 : | { | ||
138 : | *this->var() = this->_val; | ||
139 : | } | ||
140 : | |||
141 : | /********** 32-bit unsigned integer options **********/ | ||
142 : | |||
143 : | struct option_uint32 : public option_base { | ||
144 : | uint32_t _val; | ||
145 : | |||
146 : | option_uint32 (std::string const &name, std::string const &desc, uint32_t *gv, bool hasDflt) | ||
147 : | : option_base (name, desc, gv, hasDflt) | ||
148 : | { } | ||
149 : | ~option_uint32 () { } | ||
150 : | |||
151 : | uint32_t *var () const { return reinterpret_cast<uint32_t *>(this->_gv); } | ||
152 : | |||
153 : | void register_opt (hestOpt **); | ||
154 : | void init_input (); | ||
155 : | }; | ||
156 : | |||
157 : | void option_uint32::register_opt (hestOpt **hOpt) | ||
158 : | { | ||
159 : | if (this->_hasDflt) { | ||
160 : | std::ostringstream os; | ||
161 : | os << *this->var(); | ||
162 : | hestOptAdd ( | ||
163 : | hOpt, this->_name.c_str(), "int", airTypeUInt, 1, 1, &this->_val, | ||
164 : | os.str().c_str(), this->_desc.c_str()); | ||
165 : | } | ||
166 : | else { | ||
167 : | hestOptAdd ( | ||
168 : | hOpt, this->_name.c_str(), "int", airTypeUInt, 1, 1, &this->_val, | ||
169 : | nullptr, this->_desc.c_str()); | ||
170 : | } | ||
171 : | } | ||
172 : | |||
173 : | void option_uint32::init_input () | ||
174 : | { | ||
175 : | *this->var() = this->_val; | ||
176 : | } | ||
177 : | |||
178 : | /********** 64-bit integer options **********/ | ||
179 : | |||
180 : | struct option_int64 : public option_base { | ||
181 : | int64_t _val; | ||
182 : | |||
183 : | option_int64 (std::string const &name, std::string const &desc, int64_t *gv, bool hasDflt) | ||
184 : | : option_base (name, desc, gv, hasDflt) | ||
185 : | { } | ||
186 : | ~option_int64 () { } | ||
187 : | |||
188 : | int64_t *var () const { return reinterpret_cast<int64_t *>(this->_gv); } | ||
189 : | |||
190 : | void register_opt (hestOpt **); | ||
191 : | void init_input (); | ||
192 : | }; | ||
193 : | |||
194 : | void option_int64::register_opt (hestOpt **hOpt) | ||
195 : | { | ||
196 : | if (this->_hasDflt) { | ||
197 : | std::ostringstream os; | ||
198 : | os << *this->var(); | ||
199 : | hestOptAdd ( | ||
200 : | hOpt, this->_name.c_str(), "int", airTypeLongInt, 1, 1, &this->_val, | ||
201 : | os.str().c_str(), this->_desc.c_str()); | ||
202 : | } | ||
203 : | else { | ||
204 : | hestOptAdd ( | ||
205 : | hOpt, this->_name.c_str(), "int", airTypeLongInt, 1, 1, &this->_val, | ||
206 : | nullptr, this->_desc.c_str()); | ||
207 : | } | ||
208 : | } | ||
209 : | |||
210 : | void option_int64::init_input () | ||
211 : | { | ||
212 : | *this->var() = this->_val; | ||
213 : | } | ||
214 : | |||
215 : | /********** 32-bit floating-point options **********/ | ||
216 : | |||
217 : | struct option_real32 : public option_base { | ||
218 : | int _dim; | ||
219 : | float _val[4]; | ||
220 : | |||
221 : | option_real32 (std::string const &name, std::string const &desc, int dim, float *gv, bool hasDflt) | ||
222 : | : option_base (name, desc, gv, hasDflt), _dim(dim) | ||
223 : | { } | ||
224 : | ~option_real32 () { } | ||
225 : | |||
226 : | float *var () const { return reinterpret_cast<float *>(this->_gv); } | ||
227 : | |||
228 : | void register_opt (hestOpt **); | ||
229 : | void init_input (); | ||
230 : | }; | ||
231 : | |||
232 : | void option_real32::register_opt (hestOpt **hOpt) | ||
233 : | { | ||
234 : | const char *valName = nullptr; | ||
235 : | if (this->_dim == 1) { valName = "x"; } | ||
236 : | else if (this->_dim == 2) { valName = "x y"; } | ||
237 : | else if (this->_dim == 3) { valName = "x y z"; } | ||
238 : | else if (this->_dim == 4) { valName = "x y z w"; } | ||
239 : | else { | ||
240 : | std::cerr << "illegal dimension " << this->_dim << " for " << this->_name << "\n"; | ||
241 : | exit (1); | ||
242 : | } | ||
243 : | |||
244 : | if (this->_hasDflt) { | ||
245 : | std::ostringstream os; | ||
246 : | os << this->var()[0]; | ||
247 : | for (int i = 1; i < this->_dim; i++) { | ||
248 : | os << " " << this->var()[i]; | ||
249 : | } | ||
250 : | hestOptAdd ( | ||
251 : | hOpt, this->_name.c_str(), valName, airTypeFloat, this->_dim, this->_dim, | ||
252 : | &this->_val, os.str().c_str(), this->_desc.c_str()); | ||
253 : | } | ||
254 : | else { | ||
255 : | hestOptAdd ( | ||
256 : | hOpt, this->_name.c_str(), valName, airTypeFloat, this->_dim, this->_dim, | ||
257 : | &this->_val, nullptr, this->_desc.c_str()); | ||
258 : | } | ||
259 : | } | ||
260 : | |||
261 : | void option_real32::init_input () | ||
262 : | { | ||
263 : | for (int i = 0; i < this->_dim; i++) { | ||
264 : | this->var()[i] = this->_val[i]; | ||
265 : | } | ||
266 : | } | ||
267 : | |||
268 : | /********** 64-bit floating-point options **********/ | ||
269 : | |||
270 : | struct option_real64 : public option_base { | ||
271 : | int _dim; | ||
272 : | double _val[4]; | ||
273 : | |||
274 : | option_real64 (std::string const &name, std::string const &desc, int dim, double *gv, bool hasDflt) | ||
275 : | : option_base (name, desc, gv, hasDflt), _dim(dim) | ||
276 : | { } | ||
277 : | ~option_real64 () { } | ||
278 : | |||
279 : | double *var () const { return reinterpret_cast<double *>(this->_gv); } | ||
280 : | |||
281 : | void register_opt (hestOpt **); | ||
282 : | void init_input (); | ||
283 : | }; | ||
284 : | |||
285 : | void option_real64::register_opt (hestOpt **hOpt) | ||
286 : | { | ||
287 : | const char *valName = nullptr; | ||
288 : | if (this->_dim == 1) { valName = "x"; } | ||
289 : | else if (this->_dim == 2) { valName = "x y"; } | ||
290 : | else if (this->_dim == 3) { valName = "x y z"; } | ||
291 : | else if (this->_dim == 4) { valName = "x y z w"; } | ||
292 : | else { | ||
293 : | std::cerr << "illegal dimension " << this->_dim << " for " << this->_name << "\n"; | ||
294 : | exit (1); | ||
295 : | } | ||
296 : | |||
297 : | if (this->_hasDflt) { | ||
298 : | std::ostringstream os; | ||
299 : | os << this->var()[0]; | ||
300 : | for (int i = 1; i < this->_dim; i++) { | ||
301 : | os << " " << this->var()[i]; | ||
302 : | } | ||
303 : | hestOptAdd ( | ||
304 : | hOpt, this->_name.c_str(), valName, airTypeDouble, this->_dim, this->_dim, &this->_val, | ||
305 : | os.str().c_str(), this->_desc.c_str()); | ||
306 : | } | ||
307 : | else { | ||
308 : | hestOptAdd ( | ||
309 : | hOpt, this->_name.c_str(), valName, airTypeDouble, this->_dim, this->_dim, &this->_val, | ||
310 : | nullptr, this->_desc.c_str()); | ||
311 : | } | ||
312 : | } | ||
313 : | |||
314 : | void option_real64::init_input () | ||
315 : | { | ||
316 : | for (int i = 0; i < this->_dim; i++) { | ||
317 : | this->var()[i] = this->_val[i]; | ||
318 : | } | ||
319 : | } | ||
320 : | |||
321 : | /********** string options **********/ | ||
322 : | |||
323 : | struct option_string : public option_base { | ||
324 : | char *_val; | ||
325 : | |||
326 : | option_string (std::string const &name, std::string const &desc, void *gv, bool hasDflt) | ||
327 : | : option_base (name, desc, gv, hasDflt) | ||
328 : | { } | ||
329 : | ~option_string () { } | ||
330 : | |||
331 : | std::string *var () const { return reinterpret_cast<std::string *>(this->_gv); } | ||
332 : | |||
333 : | void register_opt (hestOpt **); | ||
334 : | void init_input (); | ||
335 : | }; | ||
336 : | |||
337 : | void option_string::register_opt (hestOpt **hOpt) | ||
338 : | { | ||
339 : | if (this->_hasDflt) { | ||
340 : | hestOptAdd ( | ||
341 : | hOpt, this->_name.c_str(), "str", airTypeString, 1, 1, &this->_val, | ||
342 : | this->var()->c_str(), this->_desc.c_str()); | ||
343 : | } | ||
344 : | else { | ||
345 : | hestOptAdd ( | ||
346 : | hOpt, this->_name.c_str(), "str", airTypeString, 1, 1, &this->_val, | ||
347 : | nullptr, this->_desc.c_str()); | ||
348 : | } | ||
349 : | } | ||
350 : | |||
351 : | void option_string::init_input () | ||
352 : | { | ||
353 : | *this->var() = this->_val; | ||
354 : | } | ||
355 : | |||
356 : | } // namespace __details | ||
357 : | |||
358 : | /******************** class options ********************/ | ||
359 : | |||
360 : | options::options (const char *info) | ||
361 : | : _progInfo((info == nullptr) ? "" : info) | ||
362 : | { | ||
363 : | } | ||
364 : | |||
365 : | options::~options () | ||
366 : | { | ||
367 : | for (auto it = this->_opts.begin(); it != this->_opts.end(); it++) { | ||
368 : | delete (*it); | ||
369 : | } | ||
370 : | } | ||
371 : | |||
372 : | void options::addFlag (std::string const &name, std::string const &desc, bool *gv) | ||
373 : | { | ||
374 : | this->_opts.push_back (new __details::option_flag(name, desc, gv)); | ||
375 : | } | ||
376 : | |||
377 : | void options::add (std::string const &name, std::string const &desc, bool *gv, bool hasDflt) | ||
378 : | { | ||
379 : | this->_opts.push_back (new __details::option_bool(name, desc, gv, hasDflt)); | ||
380 : | } | ||
381 : | |||
382 : | void options::add (std::string const &name, std::string const &desc, int32_t *gv, bool hasDflt) | ||
383 : | { | ||
384 : | this->_opts.push_back (new __details::option_int32(name, desc, gv, hasDflt)); | ||
385 : | } | ||
386 : | |||
387 : | void options::add (std::string const &name, std::string const &desc, uint32_t *gv, bool hasDflt) | ||
388 : | { | ||
389 : | this->_opts.push_back (new __details::option_uint32(name, desc, gv, hasDflt)); | ||
390 : | } | ||
391 : | |||
392 : | void options::add (std::string const &name, std::string const &desc, int64_t *gv, bool hasDflt) | ||
393 : | { | ||
394 : | this->_opts.push_back (new __details::option_int64(name, desc, gv, hasDflt)); | ||
395 : | } | ||
396 : | |||
397 : | void options::add (std::string const &name, std::string const &desc, float *gv, bool hasDflt) | ||
398 : | { | ||
399 : | this->_opts.push_back (new __details::option_real32(name, desc, 1, gv, hasDflt)); | ||
400 : | } | ||
401 : | |||
402 : | void options::add (std::string const &name, std::string const &desc, double *gv, bool hasDflt) | ||
403 : | { | ||
404 : | this->_opts.push_back (new __details::option_real64(name, desc, 1, gv, hasDflt)); | ||
405 : | } | ||
406 : | |||
407 : | void options::add (std::string const &name, std::string const &desc, std::string *gv, bool hasDflt) | ||
408 : | { | ||
409 : | this->_opts.push_back (new __details::option_string(name, desc, gv, hasDflt)); | ||
410 : | } | ||
411 : | |||
412 : | void options::add (std::string const &name, std::string const &desc, int dim, float *gv, bool hasDflt) | ||
413 : | { | ||
414 : | this->_opts.push_back (new __details::option_real32(name, desc, dim, gv, hasDflt)); | ||
415 : | } | ||
416 : | |||
417 : | void options::add (std::string const &name, std::string const &desc, int dim, double *gv, bool hasDflt) | ||
418 : | { | ||
419 : | this->_opts.push_back (new __details::option_real64(name, desc, dim, gv, hasDflt)); | ||
420 : | } | ||
421 : | |||
422 : | void options::process (int argc, const char **argv) | ||
423 : | { | ||
424 : | static const char *me = "Diderot_ProcessOptions"; | ||
425 : | |||
426 : | airArray *mop = airMopNew(); | ||
427 : | hestOpt *hopt = nullptr; | ||
428 : | hestParm *hparam = hestParmNew(); | ||
429 : | hparam->noArgsIsNoProblem = AIR_TRUE; | ||
430 : | airMopAdd (mop, hparam, (airMopper)hestParmFree, airMopAlways); | ||
431 : | |||
432 : | // add the "--help" option | ||
433 : | int32_t helpFlg; | ||
434 : | hestOptAdd ( | ||
435 : | &hopt, "h,help", nullptr, airTypeInt, 0, 0, &helpFlg, | ||
436 : | "false", "print usage information and exit"); | ||
437 : | |||
438 : | for (auto it = this->_opts.begin(); it != this->_opts.end(); it++) { | ||
439 : | (*it)->register_opt (&hopt); | ||
440 : | } | ||
441 : | |||
442 : | // scan for the "-h" or "--help" option. We have to do this manualy because hest | ||
443 : | // doesn't support a help flag mechanism | ||
444 : | for (int i = 1; i < argc; i++) { | ||
445 : | if (strcmp(argv[i], "-h") == 0) { | ||
446 : | // short help message | ||
447 : | hestUsage (stderr, hopt, argv[0], hparam); | ||
448 : | exit (0); | ||
449 : | } | ||
450 : | else if (strcmp(argv[i], "--help") == 0) { | ||
451 : | // long help message | ||
452 : | hestUsage (stderr, hopt, argv[0], hparam); | ||
453 : | hestGlossary (stderr, hopt, hparam); | ||
454 : | exit (0); | ||
455 : | } | ||
456 : | } | ||
457 : | |||
458 : | // if we get here, there wasn't a "-h" or "--help" option, so do regular processing | ||
459 : | hestParseOrDie ( | ||
460 : | hopt, argc-1, argv+1, hparam, argv[0], | ||
461 : | this->_progInfo.c_str(), | ||
462 : | AIR_TRUE, AIR_TRUE, AIR_TRUE); | ||
463 : | airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); | ||
464 : | airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); | ||
465 : | |||
466 : | // copy option values back into input variables | ||
467 : | for (auto it = this->_opts.begin(); it != this->_opts.end(); it++) { | ||
468 : | (*it)->init_input (); | ||
469 : | } | ||
470 : | |||
471 : | airMopOkay(mop); | ||
472 : | |||
473 : | } | ||
474 : | |||
475 : | } // namespace diderot |
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |