Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /branches/pure-cfg/src/lib/common/input.c
ViewVC logotype

Annotation of /branches/pure-cfg/src/lib/common/input.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3349 - (view) (download) (as text)

1 : jhr 1231 /*! \file input.c
2 :     *
3 : glk 1252 * \author John Reppy, Gordon Kindlmann
4 : jhr 1231 */
5 :    
6 :     /*
7 : jhr 3349 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
8 :     *
9 :     * COPYRIGHT (c) 2015 The University of Chicago
10 : jhr 1231 * All rights reserved.
11 :     */
12 :     #include "Diderot/diderot.h"
13 :     #include <teem/hest.h>
14 :    
15 : jhr 1648 bool VerboseFlg = false; //! true if running in verbose mode
16 :     bool TimingFlg = false; //! true if timing computation
17 : jhr 1649 bool NrrdOutputFlg = false; //! true if output is in Nrrd format
18 : jhr 1648
19 : jhr 1243 //! Option type tags
20 : jhr 1236 typedef enum {
21 : glk 1253 optTypeUnknown, // 0
22 :     optTypeFlag, // 1
23 :     optTypeBool, // 2
24 :     optTypeInt, // 3
25 :     optTypeReal, // 4
26 :     optTypeReal2, // 5
27 :     optTypeReal3, // 6
28 :     optTypeReal4, // 7
29 :     optTypeString // 8
30 : jhr 1262 } opt_type_t;
31 : jhr 1236
32 : jhr 1262 /*! The struct containing the definition of *one* option, and storage
33 :     * for its value once parsed
34 :     */
35 : glk 1252 typedef struct {
36 : jhr 1268 char *name; //!< option name
37 :     char *desc; //!< option description (a phrase or sentence)
38 :     opt_type_t ty; //!< option type
39 :     union { //! storage that is passed into hest
40 :     int b; //!< storage for boolean-valued options
41 :     double r[4]; //!< storage for real-valued options
42 :     int64_t i[4]; //!< storage for integer-valued options
43 :     char *s; //!< storage for string-valued options
44 : glk 1252 } hval;
45 : jhr 1268 void *valp; //!< pointer to Diderot global variable being set
46 : jhr 1262 } opt_def_t;
47 : jhr 1236
48 : jhr 1669 /*! container for *all* options, the machinery for parsing them,
49 : jhr 1262 * and means of managing their allocation. There is an opaque typedef
50 :     * around this in src/include/Diderot/options.h.
51 :     *
52 :     * The "airArray *mop" is the primary means of managing the things that
53 :     * are dynamically allocated; anything that is allocated is registered
54 :     * in the mop so that it can be freed from a single place later (look
55 :     * for calls to airMopAdd)
56 :     *
57 : jhr 1263 * Note that "odef" is a dynamically re-allocated array (managed by
58 : jhr 1262 * "odefArr"), and it is an array of opt_def_t pointers, and not an
59 :     * array of opt_def_t's, which is necessary: the values that hest sets
60 :     * are set via a pointer, and those values are stored in the opt_def_t,
61 :     * so the memory location of the opt_def_t cannot change, so these are
62 :     * allocated individually once. If odef was an array of opt_def_t's,
63 :     * then the location of the individual op_def_t would change if odef
64 :     * was reallocated for a different length.
65 :     */
66 :     struct Diderot_struct_options {
67 : jhr 1648 char *progInfo; //!< documentation string for describing whole
68 :     //! program, intended to be one or more sentences
69 : jhr 1268 hestOpt *hopt; //!< dynamically managed hest options
70 :     hestParm *hparm; //!< hest parameters
71 :     opt_def_t **odef; //!< dynamically reallocated via odefArr
72 :     unsigned int odefNum; //!< length of meaningful values in odef[]
73 :     airArray *odefArr; //!< manages odef and odefNum;
74 :     airArray *mop; //!< manages hopt, hparm, and odefArr
75 : glk 1252 };
76 : jhr 1236
77 : jhr 1262 static void *OptDefNew ()
78 :     {
79 :     opt_def_t *odef = AIR_CALLOC(1, opt_def_t);
80 :     odef->name = odef->desc = 0;
81 : glk 1252 odef->ty = optTypeUnknown;
82 : jhr 1262 odef->valp = 0;
83 :     return odef;
84 : jhr 1236 }
85 :    
86 : jhr 1262 /*! free an opt_def_t. This doesn't need to be called directly; it will
87 : jhr 1648 * be used by the airArray to manage "odef" and what it points to.
88 : jhr 1262 */
89 :     static void *optDefNix (void *_odef)
90 :     {
91 :     opt_def_t *odef = (opt_def_t *)_odef;
92 : glk 1252 airFree(odef->name);
93 :     airFree(odef->desc);
94 :     if (optTypeString == odef->ty) {
95 :     airFree(odef->hval.s);
96 : jhr 1236 }
97 : glk 1253 airFree(odef);
98 : jhr 1262 return 0;
99 : glk 1252 }
100 : jhr 1236
101 : jhr 1648 /*! create the container for all option information and register standard
102 :     * command-line options.
103 : jhr 1262 */
104 : jhr 1263 Diderot_Options_t *Diderot_OptNew ()
105 : jhr 1262 {
106 :     static const char *me = "Diderot_Options_New";
107 : jhr 1648 Diderot_Options_t *opts = AIR_CALLOC(1, Diderot_Options_t);
108 :     if (opts == 0) {
109 : glk 1260 fprintf(stderr, "%s: unable to allocate output\n", me);
110 :     exit(1);
111 : jhr 1236 }
112 : jhr 1648 opts->progInfo = 0;
113 :     opts->mop = airMopNew();
114 :     opts->hopt = 0;
115 :     opts->hparm = hestParmNew();
116 :     opts->hparm->noArgsIsNoProblem = AIR_TRUE;
117 :     airMopAdd (opts->mop, opts->hparm, (airMopper)hestParmFree, airMopAlways);
118 :     opts->odef = 0;
119 :     opts->odefNum = 0;
120 : jhr 1262 /*
121 :     ** the airArray odefArr manages the allocation of odef, and as a
122 :     ** convenience also sets odefNum to the number of values reliably
123 :     ** set in odef
124 :     */
125 : jhr 1648 opts->odefArr = airArrayNew (
126 :     (void**)(&opts->odef),
127 :     &opts->odefNum,
128 :     sizeof(opt_def_t *),
129 : jhr 1268 8 /* allocation increment */);
130 : jhr 1262
131 : jhr 1648 if (opts->odefArr == 0) {
132 : glk 1260 fprintf(stderr, "%s: unable to allocate option array\n", me);
133 :     exit(1);
134 : glk 1252 }
135 : jhr 1262 /*
136 :     ** the airArray will set odef[I] = OptDefNew for newly allocated
137 :     ** elements I of odef, and will call optDefNix(odef[I]) for
138 :     ** elements of odef that are about to be freed
139 :     */
140 : jhr 1648 airArrayPointerCB (opts->odefArr, OptDefNew, optDefNix);
141 :     airMopAdd (opts->mop, opts->odefArr, (airMopper)airArrayNuke, airMopAlways);
142 :    
143 :     // register standard command-line options
144 :     Diderot_OptAddFlag (opts, "verbose", "enable runtime-system messages", &VerboseFlg);
145 :     Diderot_OptAddFlag (opts, "timing", "enable execution timing", &TimingFlg);
146 :     Diderot_OptAddFlag (opts, "nrrd", "enable nrrd output", &NrrdOutputFlg);
147 :    
148 :     return opts;
149 : jhr 1236 }
150 :    
151 : jhr 1262 /*! free everything associated with a Diderot_Options_t
152 :     */
153 :     void Diderot_OptFree (Diderot_Options_t *dopts)
154 :     {
155 :     if (dopts != 0) {
156 : glk 1252 airFree(dopts->progInfo);
157 : glk 1260 /* frees everything connected to the mop, and the mop itself */
158 : glk 1252 airMopOkay(dopts->mop);
159 :     free(dopts);
160 :     }
161 :     return;
162 : jhr 1236 }
163 :    
164 : jhr 1262 /*! sets the one piece of information in the Diderot_Options_t
165 :     * which is not really for the options; "progInfo" is to describe the
166 :     * whole program.
167 :     */
168 :     void Diderot_OptProgramInfoSet (
169 :     Diderot_Options_t *dopts,
170 :     const char *progInfo)
171 :     {
172 :     static const char *me = "Diderot_OptProgramInfoSet";
173 : jhr 1236
174 : glk 1252 if (progInfo) {
175 :     if (!( dopts->progInfo = airStrdup(progInfo) )) {
176 : glk 1260 fprintf(stderr, "%s: unable to copy program info", me);
177 :     exit(1);
178 : glk 1252 }
179 : jhr 1236 }
180 :     }
181 :    
182 : jhr 1262 /*! main function for adding options to a Diderot_Options_t.
183 :     */
184 :     static opt_def_t *OptAdd (
185 :     Diderot_Options_t *dopts,
186 :     const char *name,
187 :     const char *desc,
188 :     void *valp,
189 :     opt_type_t ty)
190 :     {
191 :     static const char *me = "OptAdd";
192 : glk 1252 unsigned int nidx;
193 :    
194 : jhr 1262 if ((name == 0) || (desc == 0)) {
195 : glk 1260 fprintf(stderr, "%s: need both name (%p) and desc (%p) non-NULL\n",
196 : jhr 1268 me, (void *)name, (void *)desc);
197 : glk 1260 exit(1);
198 : jhr 1236 }
199 : jhr 1262 /* calling airArrayLenIncr may trigger re-allocation of odef;
200 :     * nidx is the index of the newly reserved element, odef[nidx]
201 :     */
202 : glk 1252 nidx = airArrayLenIncr(dopts->odefArr, 1);
203 : jhr 1262 if (dopts->odef == 0) {
204 : glk 1260 fprintf(stderr, "%s: unable to reallocate option array\n", me);
205 :     exit(1);
206 : glk 1252 }
207 : jhr 1262 /* code here uses "odf" to copy one value of odef[] */
208 : jhr 1263 opt_def_t *odf = dopts->odef[nidx];
209 : glk 1260 odf->name = airStrdup(name);
210 :     odf->desc = airStrdup(desc);
211 : jhr 1262 if ((odf->name == 0) || (odf->desc == 0)) {
212 :     fprintf(stderr, "%s: unable to allocate strings (%p, %p)\n",
213 : jhr 1268 me, (void *)odf->name,(void *) odf->desc);
214 : glk 1260 exit(1);
215 : glk 1252 }
216 : glk 1260 odf->valp = valp;
217 :     odf->ty = ty;
218 : glk 1252
219 : glk 1260 return odf;
220 : glk 1252 }
221 : jhr 1236
222 : jhr 1262 void Diderot_OptAddFlag (
223 :     Diderot_Options_t *dopts,
224 :     const char *name, const char *desc,
225 :     bool *flg)
226 :     {
227 :     opt_def_t *odf = OptAdd(dopts, name, desc, (void*)flg, optTypeFlag);
228 : jhr 1268 hestOptAdd (
229 :     &dopts->hopt, name, NULL, airTypeInt, 0, 0, &odf->hval.b,
230 :     NULL, desc);
231 : jhr 1236 }
232 :    
233 : jhr 1263 /*! \brief add a boolean-valued option to the list of options.
234 :     * \param dopts the list of options
235 :     * \param name the name of the option
236 :     * \param desc a short description string
237 :     * \param v a pointer to the location where the value gets stored
238 :     * \param hasDflt true if there is an initial value
239 :     */
240 : jhr 1262 void Diderot_OptAddBool (
241 :     Diderot_Options_t *dopts,
242 :     const char *name, const char *desc,
243 :     bool *v, bool hasDflt)
244 :     {
245 :     opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeBool);
246 : jhr 1268 hestOptAdd (
247 :     &dopts->hopt, name, "bool", airTypeBool, 1, 1, &odf->hval.b,
248 :     hasDflt ? (*v ? "true" : "false") : NULL, desc);
249 : glk 1252 }
250 : jhr 1236
251 : glk 1260 /*
252 :     ** On the use of AIR_STRLEN_HUGE below: default values for
253 :     ** command-line options are communicated to hest by a *string*, but
254 :     ** the actual default value comes to us in Diderot global. So these
255 :     ** functions have to convert the value from the Diderot variable into
256 :     ** a string.
257 :     **
258 :     ** The problem is that we don't know how long string will have to be,
259 :     ** and there are few good functions for dealing with this. snprintf
260 :     ** is good for making sure you don't over-write a buffer of fixed
261 :     ** size, but you still have to allocate the buffer. asprintf allocates
262 :     ** as needed, but GLK didn't want to assume it was available (perhaps
263 :     ** this should be revisited)
264 :     **
265 :     ** So instead, we just use a huge buffer, and assume that it will be
266 :     ** more than big enough. Feel free to fix this.
267 :     */
268 :    
269 : jhr 1262 /*! \brief add an integer option to the list of options.
270 :     * \param dopts the list of options
271 :     * \param name the name of the option
272 :     * \param desc a short description string
273 :     * \param v a pointer to the location where the value gets stored
274 :     * \param hasDflt true if there is an initial value
275 :     */
276 :     void Diderot_OptAddInt (
277 :     Diderot_Options_t *dopts,
278 :     const char *name, const char *desc, Diderot_int_t *v, bool hasDflt)
279 :     {
280 : glk 1252 char buf[AIR_STRLEN_HUGE] = "";
281 : jhr 1236 if (hasDflt) {
282 : jhr 1649 snprintf(buf, sizeof(buf), "%ld", (long)*v);
283 : jhr 1236 }
284 : jhr 1262 opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeInt);
285 : jhr 1268 hestOptAdd (
286 :     &dopts->hopt, name, "int", airTypeLongInt, 1, 1, odf->hval.i,
287 :     hasDflt ? buf : NULL, desc);
288 : jhr 1236 }
289 :    
290 : jhr 1262 /*! \brief add a real-valued option to the list of options.
291 :     * \param dopts the list of options
292 :     * \param name the name of the option
293 :     * \param desc a short description string
294 :     * \param v a pointer to the location where the value gets stored
295 :     * \param hasDflt true if there is an initial value
296 :     */
297 :     void Diderot_OptAddReal (
298 :     Diderot_Options_t *dopts,
299 :     const char *name, const char *desc, Diderot_real_t *v, bool hasDflt)
300 :     {
301 : glk 1252 char buf[AIR_STRLEN_HUGE] = "";
302 : jhr 1236 if (hasDflt) {
303 : jhr 1649 snprintf(buf, sizeof(buf), "%lf", (double)*v);
304 : jhr 1236 }
305 : jhr 1262 opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal);
306 : jhr 1268 hestOptAdd (
307 :     &dopts->hopt, name, "val", airTypeDouble, 1, 1, odf->hval.r,
308 :     hasDflt ? buf : NULL, desc);
309 : jhr 1236 }
310 :    
311 : jhr 1262 /*! \brief add a 2-element vector option to the list of options.
312 :     * \param dopts the list of options
313 :     * \param name the name of the option
314 :     * \param desc a short description string
315 :     * \param v a pointer to the location where the value gets stored
316 :     * \param hasDflt true if there is an initial value
317 :     */
318 :     void Diderot_OptAddReal2 (
319 :     Diderot_Options_t *dopts,
320 :     const char *name, const char *desc, Diderot_vec2_t *v, bool hasDflt)
321 :     {
322 : glk 1252 char buf[AIR_STRLEN_HUGE] = "";
323 : jhr 1236
324 :     if (hasDflt) {
325 : glk 1252 Diderot_union2_t u;
326 :     u.v = *v;
327 : jhr 1649 snprintf(buf, sizeof(buf), "%lf %lf", (double)(u.r[0]), (double)(u.r[1]));
328 : jhr 1236 }
329 : jhr 1262 opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal2);
330 : jhr 1268 hestOptAdd (
331 :     &dopts->hopt, name, "x y", airTypeDouble, 2, 2, odf->hval.r,
332 :     hasDflt ? buf : NULL, desc);
333 : jhr 1236 }
334 :    
335 : jhr 1262 /*! \brief add a 3-element vector option to the list of options.
336 :     * \param dopts the list of options
337 :     * \param name the name of the option
338 :     * \param desc a short description string
339 :     * \param v a pointer to the location where the value gets stored
340 :     * \param hasDflt true if there is an initial value
341 :     */
342 :     void Diderot_OptAddReal3 (
343 :     Diderot_Options_t *dopts,
344 :     const char *name, const char *desc, Diderot_vec3_t *v, bool hasDflt)
345 :     {
346 : glk 1252 char buf[AIR_STRLEN_HUGE] = "";
347 : jhr 1236
348 :     if (hasDflt) {
349 : glk 1252 Diderot_union3_t u;
350 :     u.v = *v;
351 : jhr 1649 snprintf(buf, sizeof(buf), "%lf %lf %lf",
352 :     (double)(u.r[0]), (double)(u.r[1]), (double)(u.r[2]));
353 : jhr 1236 }
354 : jhr 1262 opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal3);
355 : jhr 1268 hestOptAdd (
356 :     &dopts->hopt, name, "x y z", airTypeDouble, 3, 3, odf->hval.r,
357 :     hasDflt ? buf : NULL, desc);
358 : jhr 1236 }
359 :    
360 : jhr 1262 /*! \brief add a 4-element vector option to the list of options.
361 :     * \param dopts the list of options
362 :     * \param name the name of the option
363 :     * \param desc a short description string
364 :     * \param v a pointer to the location where the value gets stored
365 :     * \param hasDflt true if there is an initial value
366 :     */
367 :     void Diderot_OptAddReal4 (
368 :     Diderot_Options_t *dopts,
369 :     const char *name, const char *desc,
370 :     Diderot_vec4_t *v, bool hasDflt)
371 :     {
372 : glk 1252 char buf[AIR_STRLEN_HUGE] = "";
373 : jhr 1236
374 :     if (hasDflt) {
375 : glk 1252 Diderot_union4_t u;
376 :     u.v = *v;
377 : jhr 1649 snprintf(buf, sizeof(buf), "%lf %lf %lf %lf",
378 : jhr 1268 (double)(u.r[0]), (double)(u.r[1]),
379 :     (double)(u.r[2]), (double)(u.r[3]));
380 : jhr 1236 }
381 : jhr 1262 opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal4);
382 : jhr 1268 hestOptAdd (
383 :     &dopts->hopt, name, "x y z w", airTypeDouble, 4, 4, odf->hval.r,
384 :     hasDflt ? buf : NULL, desc);
385 : glk 1252 }
386 : jhr 1236
387 : jhr 1262 /*! \brief add a string-vauled option to the list of options.
388 :     * \param dopts the list of options
389 :     * \param name the name of the option
390 :     * \param desc a short description string
391 :     * \param v a pointer to the location where the value gets stored
392 :     * \param hasDflt true if there is an initial value
393 :     */
394 :     void Diderot_OptAddString (
395 :     Diderot_Options_t *dopts,
396 :     const char *name, const char *desc,
397 :     char **v, bool hasDflt)
398 :     {
399 :     opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeString);
400 : jhr 1268 hestOptAdd (
401 :     &dopts->hopt, name, "str", airTypeString, 1, 1, &odf->hval.s,
402 :     hasDflt ? *v : NULL, desc);
403 : jhr 1236 }
404 :    
405 : jhr 1262 /*! given argc/argv, learn values for all options and set them
406 :     */
407 :     void Diderot_OptProcess (Diderot_Options_t *dopts, int argc, const char **argv)
408 :     {
409 :     static const char *me = "Diderot_ProcessOptions";
410 : jhr 1236
411 : jhr 1268 hestParseOrDie (
412 :     dopts->hopt, argc-1, argv+1, dopts->hparm, argv[0],
413 :     dopts->progInfo ? dopts->progInfo : "(no program info set)",
414 :     AIR_TRUE, AIR_TRUE, AIR_TRUE);
415 : glk 1260 airMopAdd(dopts->mop, dopts->hopt, (airMopper)hestOptFree, airMopAlways);
416 :     airMopAdd(dopts->mop, dopts->hopt, (airMopper)hestParseFree, airMopAlways);
417 : jhr 1236
418 : glk 1252 // convert values learned by hest to their Diderot representations
419 :     for (int i = 0; i < dopts->odefNum; i++) {
420 : jhr 1263 opt_def_t *odf = dopts->odef[i];
421 : glk 1260 switch (odf->ty) {
422 : jhr 1268 case optTypeFlag:
423 :     case optTypeBool:
424 : glk 1260 *(bool*)(odf->valp) = odf->hval.b ? true : false;
425 : glk 1252 break;
426 : jhr 1268 case optTypeInt:
427 : glk 1260 *(Diderot_int_t *)(odf->valp) = (Diderot_int_t)(odf->hval.i[0]);
428 : glk 1252 break;
429 : jhr 1268 case optTypeReal:
430 : glk 1260 *(Diderot_real_t *)(odf->valp) = (Diderot_real_t)(odf->hval.r[0]);
431 : glk 1252 break;
432 : jhr 1268 case optTypeReal2:
433 : glk 1260 *(Diderot_vec2_t *)(odf->valp) = vec2((Diderot_real_t)(odf->hval.r[0]),
434 :     (Diderot_real_t)(odf->hval.r[1]));
435 : glk 1252 break;
436 : jhr 1268 case optTypeReal3:
437 : glk 1260 *(Diderot_vec3_t *)(odf->valp) = vec3((Diderot_real_t)(odf->hval.r[0]),
438 :     (Diderot_real_t)(odf->hval.r[1]),
439 :     (Diderot_real_t)(odf->hval.r[2]));
440 : glk 1252 break;
441 : jhr 1268 case optTypeReal4:
442 : glk 1260 *(Diderot_vec4_t *)(odf->valp) = vec4((Diderot_real_t)(odf->hval.r[0]),
443 :     (Diderot_real_t)(odf->hval.r[1]),
444 :     (Diderot_real_t)(odf->hval.r[2]),
445 :     (Diderot_real_t)(odf->hval.r[3]));
446 : glk 1252 break;
447 : jhr 1268 case optTypeString: {
448 :     char *s = airStrdup(odf->hval.s);
449 :     if (s == 0) {
450 :     fprintf(stderr, "%s: unable to allocate string copy\n", me);
451 :     exit(1);
452 :     }
453 :     *(char **)(odf->valp) = s;
454 : jhr 1262 } break;
455 : jhr 1268 default:
456 : glk 1260 fprintf(stderr, "%s: unknown option type %d\n", me, odf->ty);
457 :     exit(1);
458 : jhr 1268 } /* switch */
459 : jhr 1243 }
460 : jhr 1236 }

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0