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

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