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

SCM Repository

[diderot] Diff of /trunk/src/lib/common/input.c
ViewVC logotype

Diff of /trunk/src/lib/common/input.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1232, Mon May 16 23:37:52 2011 UTC revision 1301, Thu Jun 9 23:58:40 2011 UTC
# Line 1  Line 1 
1  /*! \file input.c  /*! \file input.c
2   *   *
3   * \author John Reppy   * \author John Reppy, Gordon Kindlmann
4   */   */
5    
6  /*  /*
# Line 14  Line 14 
14  #if defined(DIDEROT_SINGLE_PRECISION)  #if defined(DIDEROT_SINGLE_PRECISION)
15  #define vec2(a,b)               vec2f(a,b)  #define vec2(a,b)               vec2f(a,b)
16  #define vec3(a,b,c)             vec3f(a,b,c)  #define vec3(a,b,c)             vec3f(a,b,c)
17    #define vec4(a,b,c,d)  vec4f(a,b,c,d)
18  #else  #else
19  #define vec2(a,b)               vec2d(a,b)  #define vec2(a,b)               vec2d(a,b)
20  #define vec3(a,b,c)             vec3d(a,b,c)  #define vec3(a,b,c)             vec3d(a,b,c)
21    #define vec4(a,b,c,d)  vec4d(a,b,c,d)
22  #endif  #endif
23    
24  Status_t Diderot_InputString (const char *name, const char **v, bool hasDflt)  //! Option type tags
25    typedef enum {
26        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    } opt_type_t;
36    
37    /*! The struct containing the definition of *one* option, and storage
38     *  for its value once parsed
39     */
40    typedef struct {
41        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        } hval;
50        void        *valp;          //!< pointer to Diderot global variable being set
51    } opt_def_t;
52    
53    /*! 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        unsigned int odefNum;       //!< length of meaningful values in odef[]
78        airArray    *odefArr;       //!< manages odef and odefNum;
79        airArray    *mop;           //!< manages hopt, hparm, and odefArr
80    };
81    
82    static void *OptDefNew ()
83  {  {
84      return DIDEROT_FAIL;      opt_def_t *odef = AIR_CALLOC(1, opt_def_t);
85        odef->name = odef->desc = 0;
86        odef->ty = optTypeUnknown;
87        odef->valp = 0;
88        return odef;
89  }  }
90    
91  Status_t Diderot_InputReal (const char *name, Diderot_real_t *v, bool hasDflt)  /*! 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      char        buf[256];      opt_def_t *odef = (opt_def_t *)_odef;
97      double      f;      airFree(odef->name);
98        airFree(odef->desc);
99        if (optTypeString == odef->ty) {
100            airFree(odef->hval.s);
101        }
102        airFree(odef);
103        return 0;
104    }
105    
106      while (true) {  /*! create the container for all option information
107          if (hasDflt)   */
108              printf("Enter value for %s (default %lf): ", name, (double)*v);  Diderot_Options_t *Diderot_OptNew ()
109          else  {
110              printf("Enter value for %s: ", name);      static const char *me = "Diderot_Options_New";
111          fflush (stdout);      Diderot_Options_t *dopts = AIR_CALLOC(1, Diderot_Options_t);
112        if (dopts == 0) {
113            fprintf(stderr, "%s: unable to allocate output\n", me);
114            exit(1);
115        }
116        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      /*
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            fprintf(stderr, "%s: unable to allocate option array\n", me);
137            exit(1);
138        }
139      /*
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    
147          char *p = fgets(buf, sizeof(buf), stdin);      return dopts;
         if (p == NULL)  
             return DIDEROT_FAIL;        // EOF  
         int n = sscanf(buf, "%lf\n", &f);  
         if (n == 1) {  
             *v = (Diderot_real_t)f;  
             return DIDEROT_OK;;  
148          }          }
149          else if (hasDflt)  
150              return DIDEROT_OK;;  /*! free everything associated with a Diderot_Options_t
151     */
152    void Diderot_OptFree (Diderot_Options_t *dopts)
153    {
154        if (dopts != 0) {
155            airFree(dopts->progInfo);
156            /* frees everything connected to the mop, and the mop itself */
157            airMopOkay(dopts->mop);
158            free(dopts);
159        }
160        return;
161      }      }
162    
163    /*! 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    
173        if (progInfo) {
174            if (!( dopts->progInfo = airStrdup(progInfo) )) {
175                fprintf(stderr, "%s: unable to copy program info", me);
176                exit(1);
177            }
178  }  }
179    }
180    
181    /*! 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        unsigned int nidx;
192    
193  Status_t Diderot_InputVec2 (const char *name, Diderot_vec2_t *v, bool hasDflt)      if ((name == 0) || (desc == 0)) {
194            fprintf(stderr, "%s: need both name (%p) and desc (%p) non-NULL\n",
195                me, (void *)name, (void *)desc);
196            exit(1);
197        }
198      /* calling airArrayLenIncr may trigger re-allocation of odef;
199       * nidx is the index of the newly reserved element, odef[nidx]
200       */
201        nidx = airArrayLenIncr(dopts->odefArr, 1);
202        if (dopts->odef == 0) {
203            fprintf(stderr, "%s: unable to reallocate option array\n", me);
204            exit(1);
205        }
206      /* code here uses "odf" to copy one value of odef[] */
207        opt_def_t *odf = dopts->odef[nidx];
208        odf->name = airStrdup(name);
209        odf->desc = airStrdup(desc);
210        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            exit(1);
214        }
215        odf->valp = valp;
216        odf->ty = ty;
217    
218        return odf;
219    }
220    
221    void Diderot_OptAddFlag (
222        Diderot_Options_t *dopts,
223        const char *name, const char *desc,
224        bool *flg)
225  {  {
226      char        buf[256];      opt_def_t *odf = OptAdd(dopts, name, desc, (void*)flg, optTypeFlag);
227      double      f1, f2;      hestOptAdd (
228            &dopts->hopt, name, NULL, airTypeInt, 0, 0, &odf->hval.b,
229            NULL, desc);
230    }
231    
232      while (true) {  /*! \brief add a boolean-valued option to the list of options.
233     *  \param dopts   the list of options
234     *  \param name    the name of the option
235     *  \param desc    a short description string
236     *  \param v       a pointer to the location where the value gets stored
237     *  \param hasDflt true if there is an initial value
238     */
239    void Diderot_OptAddBool (
240        Diderot_Options_t *dopts,
241        const char *name, const char *desc,
242        bool *v, bool hasDflt)
243    {
244        opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeBool);
245        hestOptAdd (
246            &dopts->hopt, name, "bool", airTypeBool, 1, 1, &odf->hval.b,
247            hasDflt ? (*v ? "true" : "false") : NULL, desc);
248    }
249    
250    /*
251    ** On the use of AIR_STRLEN_HUGE below: default values for
252    ** command-line options are communicated to hest by a *string*, but
253    ** the actual default value comes to us in Diderot global.  So these
254    ** functions have to convert the value from the Diderot variable into
255    ** a string.
256    **
257    ** The problem is that we don't know how long string will have to be,
258    ** and there are few good functions for dealing with this.  snprintf
259    ** is good for making sure you don't over-write a buffer of fixed
260    ** size, but you still have to allocate the buffer.  asprintf allocates
261    ** as needed, but GLK didn't want to assume it was available (perhaps
262    ** this should be revisited)
263    **
264    ** So instead, we just use a huge buffer, and assume that it will be
265    ** more than big enough.  Feel free to fix this.
266    */
267    
268    /*! \brief add an integer option to the list of options.
269     *  \param dopts   the list of options
270     *  \param name    the name of the option
271     *  \param desc    a short description string
272     *  \param v       a pointer to the location where the value gets stored
273     *  \param hasDflt true if there is an initial value
274     */
275    void Diderot_OptAddInt (
276        Diderot_Options_t *dopts,
277        const char *name, const char *desc, Diderot_int_t *v, bool hasDflt)
278    {
279        char buf[AIR_STRLEN_HUGE] = "";
280          if (hasDflt) {          if (hasDflt) {
281              Diderot_union2_t u;          sprintf(buf, "%ld", (long)*v);
282              u.v = *v;      }
283              printf("Enter value for %s (default %f %f): ",      opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeInt);
284                  name, (double)(u.r[0]), (double)(u.r[1]));      hestOptAdd (
285            &dopts->hopt, name, "int", airTypeLongInt, 1, 1, odf->hval.i,
286            hasDflt ? buf : NULL, desc);
287          }          }
         else  
             printf("Enter value for %s: ", name);  
         fflush (stdout);  
288    
289          char *p = fgets(buf, sizeof(buf), stdin);  /*! \brief add a real-valued option to the list of options.
290          if (p == NULL)   *  \param dopts   the list of options
291              return DIDEROT_FAIL;        // EOF   *  \param name    the name of the option
292          int n = sscanf(buf, "%lf %lf\n", &f1, &f2);   *  \param desc    a short description string
293          if (n == 2) {   *  \param v       a pointer to the location where the value gets stored
294              *v = vec2((Diderot_real_t)f1, (Diderot_real_t)f2);   *  \param hasDflt true if there is an initial value
295              return DIDEROT_OK;;   */
296    void Diderot_OptAddReal (
297        Diderot_Options_t *dopts,
298        const char *name, const char *desc, Diderot_real_t *v, bool hasDflt)
299    {
300        char buf[AIR_STRLEN_HUGE] = "";
301        if (hasDflt) {
302            sprintf(buf, "%lf", (double)*v);
303          }          }
304          else if (hasDflt)      opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal);
305              return DIDEROT_OK;;      hestOptAdd (
306            &dopts->hopt, name, "val", airTypeDouble, 1, 1, odf->hval.r,
307            hasDflt ? buf : NULL, desc);
308      }      }
309    
310    /*! \brief add a 2-element vector option to the list of options.
311     *  \param dopts   the list of options
312     *  \param name    the name of the option
313     *  \param desc    a short description string
314     *  \param v       a pointer to the location where the value gets stored
315     *  \param hasDflt true if there is an initial value
316     */
317    void Diderot_OptAddReal2 (
318        Diderot_Options_t *dopts,
319        const char *name, const char *desc, Diderot_vec2_t *v, bool hasDflt)
320    {
321        char buf[AIR_STRLEN_HUGE] = "";
322    
323        if (hasDflt) {
324            Diderot_union2_t u;
325            u.v = *v;
326            sprintf(buf, "%lf %lf", (double)(u.r[0]), (double)(u.r[1]));
327        }
328        opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal2);
329        hestOptAdd (
330            &dopts->hopt, name, "x y", airTypeDouble, 2, 2, odf->hval.r,
331            hasDflt ? buf : NULL, desc);
332  }  }
333    
334  Status_t Diderot_InputVec3 (const char *name, Diderot_vec3_t *v, bool hasDflt)  /*! \brief add a 3-element vector option to the list of options.
335     *  \param dopts   the list of options
336     *  \param name    the name of the option
337     *  \param desc    a short description string
338     *  \param v       a pointer to the location where the value gets stored
339     *  \param hasDflt true if there is an initial value
340     */
341    void Diderot_OptAddReal3 (
342        Diderot_Options_t *dopts,
343        const char *name, const char *desc, Diderot_vec3_t *v, bool hasDflt)
344  {  {
345      char        buf[256];      char buf[AIR_STRLEN_HUGE] = "";
     double      f1, f2, f3;  
346    
     while (true) {  
347          if (hasDflt) {          if (hasDflt) {
348              Diderot_union3_t u;              Diderot_union3_t u;
349              u.v = *v;              u.v = *v;
350              printf("Enter value for %s (default %f %f %f): ",          sprintf(buf, "%lf %lf %lf",
351                  name, (double)(u.r[0]), (double)(u.r[1]), (double)(u.r[2]));                  (double)(u.r[0]), (double)(u.r[1]), (double)(u.r[2]));
352          }          }
353          else      opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal3);
354              printf("Enter value for %s: ", name);      hestOptAdd (
355          fflush (stdout);          &dopts->hopt, name, "x y z", airTypeDouble, 3, 3, odf->hval.r,
356            hasDflt ? buf : NULL, desc);
         char *p = fgets(buf, sizeof(buf), stdin);  
         if (p == NULL)  
             return DIDEROT_FAIL;        // EOF  
         int n = sscanf(buf, "%lf %lf %lf\n", &f1, &f2, &f3);  
         if (n == 3) {  
             *v = vec3((Diderot_real_t)f1, (Diderot_real_t)f2, (Diderot_real_t)f3);  
             return DIDEROT_OK;;  
357          }          }
358          else if (hasDflt)  
359              return DIDEROT_OK;;  /*! \brief add a 4-element vector option to the list of options.
360     *  \param dopts   the list of options
361     *  \param name    the name of the option
362     *  \param desc    a short description string
363     *  \param v       a pointer to the location where the value gets stored
364     *  \param hasDflt true if there is an initial value
365     */
366    void Diderot_OptAddReal4 (
367        Diderot_Options_t *dopts,
368        const char *name, const char *desc,
369        Diderot_vec4_t *v, bool hasDflt)
370    {
371        char buf[AIR_STRLEN_HUGE] = "";
372    
373        if (hasDflt) {
374            Diderot_union4_t u;
375            u.v = *v;
376            sprintf(buf, "%lf %lf %lf %lf",
377                (double)(u.r[0]), (double)(u.r[1]),
378                (double)(u.r[2]), (double)(u.r[3]));
379        }
380        opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal4);
381        hestOptAdd (
382            &dopts->hopt, name, "x y z w", airTypeDouble, 4, 4, odf->hval.r,
383            hasDflt ? buf : NULL, desc);
384    }
385    
386    /*! \brief add a string-vauled option to the list of options.
387     *  \param dopts   the list of options
388     *  \param name    the name of the option
389     *  \param desc    a short description string
390     *  \param v       a pointer to the location where the value gets stored
391     *  \param hasDflt true if there is an initial value
392     */
393    void Diderot_OptAddString (
394        Diderot_Options_t *dopts,
395        const char *name, const char *desc,
396        char **v, bool hasDflt)
397    {
398        opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeString);
399        hestOptAdd (
400            &dopts->hopt, name, "str", airTypeString, 1, 1, &odf->hval.s,
401            hasDflt ? *v : NULL, desc);
402      }      }
403    
404    /*! given argc/argv, learn values for all options and set them
405     */
406    void Diderot_OptProcess (Diderot_Options_t *dopts, int argc, const char **argv)
407    {
408        static const char *me = "Diderot_ProcessOptions";
409    
410        hestParseOrDie (
411            dopts->hopt, argc-1, argv+1, dopts->hparm, argv[0],
412            dopts->progInfo ? dopts->progInfo : "(no program info set)",
413            AIR_TRUE, AIR_TRUE, AIR_TRUE);
414        airMopAdd(dopts->mop, dopts->hopt, (airMopper)hestOptFree, airMopAlways);
415        airMopAdd(dopts->mop, dopts->hopt, (airMopper)hestParseFree, airMopAlways);
416    
417        // convert values learned by hest to their Diderot representations
418        for (int i = 0;  i < dopts->odefNum;  i++) {
419            opt_def_t *odf = dopts->odef[i];
420            switch (odf->ty) {
421              case optTypeFlag:
422              case optTypeBool:
423                *(bool*)(odf->valp) = odf->hval.b ? true : false;
424                break;
425              case optTypeInt:
426                *(Diderot_int_t *)(odf->valp) = (Diderot_int_t)(odf->hval.i[0]);
427                break;
428              case optTypeReal:
429                *(Diderot_real_t *)(odf->valp) = (Diderot_real_t)(odf->hval.r[0]);
430                break;
431              case optTypeReal2:
432                *(Diderot_vec2_t *)(odf->valp) = vec2((Diderot_real_t)(odf->hval.r[0]),
433                                                      (Diderot_real_t)(odf->hval.r[1]));
434                break;
435              case optTypeReal3:
436                *(Diderot_vec3_t *)(odf->valp) = vec3((Diderot_real_t)(odf->hval.r[0]),
437                                                      (Diderot_real_t)(odf->hval.r[1]),
438                                                      (Diderot_real_t)(odf->hval.r[2]));
439                break;
440              case optTypeReal4:
441                *(Diderot_vec4_t *)(odf->valp) = vec4((Diderot_real_t)(odf->hval.r[0]),
442                                                      (Diderot_real_t)(odf->hval.r[1]),
443                                                      (Diderot_real_t)(odf->hval.r[2]),
444                                                      (Diderot_real_t)(odf->hval.r[3]));
445                break;
446              case optTypeString: {
447                    char *s = airStrdup(odf->hval.s);
448                    if (s == 0) {
449                        fprintf(stderr, "%s: unable to allocate string copy\n", me);
450                        exit(1);
451                    }
452                    *(char **)(odf->valp) = s;
453                } break;
454              default:
455                fprintf(stderr, "%s: unknown option type %d\n", me, odf->ty);
456                exit(1);
457            } /* switch */
458        }
459  }  }

Legend:
Removed from v.1232  
changed lines
  Added in v.1301

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