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

SCM Repository

[diderot] Annotation of /branches/vis12/src/lib/common/input.c
ViewVC logotype

Annotation of /branches/vis12/src/lib/common/input.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

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