SCM Repository
View of /branches/pure-cfg/src/lib/common/input.c
Parent Directory
|
Revision Log
Revision 1268 -
(download)
(as text)
(annotate)
Sun Jun 5 11:25:58 2011 UTC (10 years, 11 months ago) by jhr
File size: 16185 byte(s)
Sun Jun 5 11:25:58 2011 UTC (10 years, 11 months ago) by jhr
File size: 16185 byte(s)
expand tabs to avoid editor differences
/*! \file input.c * * \author John Reppy, Gordon Kindlmann */ /* * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu) * All rights reserved. */ #include "Diderot/diderot.h" #include <teem/hest.h> /* FIXME: eventally we should change the naming conventions in the header files to be generic */ #if defined(DIDEROT_SINGLE_PRECISION) #define vec2(a,b) vec2f(a,b) #define vec3(a,b,c) vec3f(a,b,c) #define vec4(a,b,c,d) vec4f(a,b,c,d) #else #define vec2(a,b) vec2d(a,b) #define vec3(a,b,c) vec3d(a,b,c) #define vec4(a,b,c,d) vec4d(a,b,c,d) #endif //! Option type tags typedef enum { optTypeUnknown, // 0 optTypeFlag, // 1 optTypeBool, // 2 optTypeInt, // 3 optTypeReal, // 4 optTypeReal2, // 5 optTypeReal3, // 6 optTypeReal4, // 7 optTypeString // 8 } opt_type_t; /*! The struct containing the definition of *one* option, and storage * for its value once parsed */ typedef struct { char *name; //!< option name char *desc; //!< option description (a phrase or sentence) opt_type_t ty; //!< option type union { //! storage that is passed into hest int b; //!< storage for boolean-valued options double r[4]; //!< storage for real-valued options int64_t i[4]; //!< storage for integer-valued options char *s; //!< storage for string-valued options } hval; void *valp; //!< pointer to Diderot global variable being set } opt_def_t; /*! container for *all* options, and the machinery for parsing them, * and means of managing their allocation. There is an opaque typedef * around this in src/include/Diderot/options.h. * * The "airArray *mop" is the primary means of managing the things that * are dynamically allocated; anything that is allocated is registered * in the mop so that it can be freed from a single place later (look * for calls to airMopAdd) * * Note that "odef" is a dynamically re-allocated array (managed by * "odefArr"), and it is an array of opt_def_t pointers, and not an * array of opt_def_t's, which is necessary: the values that hest sets * are set via a pointer, and those values are stored in the opt_def_t, * so the memory location of the opt_def_t cannot change, so these are * allocated individually once. If odef was an array of opt_def_t's, * then the location of the individual op_def_t would change if odef * was reallocated for a different length. */ struct Diderot_struct_options { char *progInfo; //!< documentation string for describing whole program, //! intended to be one or more sentences hestOpt *hopt; //!< dynamically managed hest options hestParm *hparm; //!< hest parameters opt_def_t **odef; //!< dynamically reallocated via odefArr unsigned int odefNum; //!< length of meaningful values in odef[] airArray *odefArr; //!< manages odef and odefNum; airArray *mop; //!< manages hopt, hparm, and odefArr }; static void *OptDefNew () { opt_def_t *odef = AIR_CALLOC(1, opt_def_t); odef->name = odef->desc = 0; odef->ty = optTypeUnknown; odef->valp = 0; return odef; } /*! free an opt_def_t. This doesn't need to be called directly; it will * be used by the airArray to manage "odef" and what it points to. */ static void *optDefNix (void *_odef) { opt_def_t *odef = (opt_def_t *)_odef; airFree(odef->name); airFree(odef->desc); if (optTypeString == odef->ty) { airFree(odef->hval.s); } airFree(odef); return 0; } /*! create the container for all option information */ Diderot_Options_t *Diderot_OptNew () { static const char *me = "Diderot_Options_New"; Diderot_Options_t *dopts = AIR_CALLOC(1, Diderot_Options_t); if (dopts == 0) { fprintf(stderr, "%s: unable to allocate output\n", me); exit(1); } dopts->progInfo = NULL; dopts->mop = airMopNew(); dopts->hopt = NULL; dopts->hparm = hestParmNew(); dopts->hparm->noArgsIsNoProblem = AIR_TRUE; airMopAdd(dopts->mop, dopts->hparm, (airMopper)hestParmFree, airMopAlways); dopts->odef = NULL; dopts->odefNum = 0; /* ** the airArray odefArr manages the allocation of odef, and as a ** convenience also sets odefNum to the number of values reliably ** set in odef */ dopts->odefArr = airArrayNew ( (void**)(&dopts->odef), &dopts->odefNum, sizeof(opt_def_t*), 8 /* allocation increment */); if (dopts->odefArr == 0) { fprintf(stderr, "%s: unable to allocate option array\n", me); exit(1); } /* ** the airArray will set odef[I] = OptDefNew for newly allocated ** elements I of odef, and will call optDefNix(odef[I]) for ** elements of odef that are about to be freed */ airArrayPointerCB (dopts->odefArr, OptDefNew, optDefNix); airMopAdd (dopts->mop, dopts->odefArr, (airMopper)airArrayNuke, airMopAlways); return dopts; } /*! free everything associated with a Diderot_Options_t */ void Diderot_OptFree (Diderot_Options_t *dopts) { if (dopts != 0) { airFree(dopts->progInfo); /* frees everything connected to the mop, and the mop itself */ airMopOkay(dopts->mop); free(dopts); } return; } /*! sets the one piece of information in the Diderot_Options_t * which is not really for the options; "progInfo" is to describe the * whole program. */ void Diderot_OptProgramInfoSet ( Diderot_Options_t *dopts, const char *progInfo) { static const char *me = "Diderot_OptProgramInfoSet"; if (progInfo) { if (!( dopts->progInfo = airStrdup(progInfo) )) { fprintf(stderr, "%s: unable to copy program info", me); exit(1); } } } /*! main function for adding options to a Diderot_Options_t. */ static opt_def_t *OptAdd ( Diderot_Options_t *dopts, const char *name, const char *desc, void *valp, opt_type_t ty) { static const char *me = "OptAdd"; unsigned int nidx; if ((name == 0) || (desc == 0)) { fprintf(stderr, "%s: need both name (%p) and desc (%p) non-NULL\n", me, (void *)name, (void *)desc); exit(1); } /* calling airArrayLenIncr may trigger re-allocation of odef; * nidx is the index of the newly reserved element, odef[nidx] */ nidx = airArrayLenIncr(dopts->odefArr, 1); if (dopts->odef == 0) { fprintf(stderr, "%s: unable to reallocate option array\n", me); exit(1); } /* code here uses "odf" to copy one value of odef[] */ opt_def_t *odf = dopts->odef[nidx]; odf->name = airStrdup(name); odf->desc = airStrdup(desc); if ((odf->name == 0) || (odf->desc == 0)) { fprintf(stderr, "%s: unable to allocate strings (%p, %p)\n", me, (void *)odf->name,(void *) odf->desc); exit(1); } odf->valp = valp; odf->ty = ty; return odf; } void Diderot_OptAddFlag ( Diderot_Options_t *dopts, const char *name, const char *desc, bool *flg) { opt_def_t *odf = OptAdd(dopts, name, desc, (void*)flg, optTypeFlag); hestOptAdd ( &dopts->hopt, name, NULL, airTypeInt, 0, 0, &odf->hval.b, NULL, desc); } /*! \brief add a boolean-valued option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddBool ( Diderot_Options_t *dopts, const char *name, const char *desc, bool *v, bool hasDflt) { opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeBool); hestOptAdd ( &dopts->hopt, name, "bool", airTypeBool, 1, 1, &odf->hval.b, hasDflt ? (*v ? "true" : "false") : NULL, desc); } /* ** On the use of AIR_STRLEN_HUGE below: default values for ** command-line options are communicated to hest by a *string*, but ** the actual default value comes to us in Diderot global. So these ** functions have to convert the value from the Diderot variable into ** a string. ** ** The problem is that we don't know how long string will have to be, ** and there are few good functions for dealing with this. snprintf ** is good for making sure you don't over-write a buffer of fixed ** size, but you still have to allocate the buffer. asprintf allocates ** as needed, but GLK didn't want to assume it was available (perhaps ** this should be revisited) ** ** So instead, we just use a huge buffer, and assume that it will be ** more than big enough. Feel free to fix this. */ /*! \brief add an integer option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddInt ( Diderot_Options_t *dopts, const char *name, const char *desc, Diderot_int_t *v, bool hasDflt) { char buf[AIR_STRLEN_HUGE] = ""; if (hasDflt) { sprintf(buf, "%ld", (long)*v); } opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeInt); hestOptAdd ( &dopts->hopt, name, "int", airTypeLongInt, 1, 1, odf->hval.i, hasDflt ? buf : NULL, desc); } /*! \brief add a real-valued option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddReal ( Diderot_Options_t *dopts, const char *name, const char *desc, Diderot_real_t *v, bool hasDflt) { char buf[AIR_STRLEN_HUGE] = ""; if (hasDflt) { sprintf(buf, "%lf", (double)*v); } opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal); hestOptAdd ( &dopts->hopt, name, "val", airTypeDouble, 1, 1, odf->hval.r, hasDflt ? buf : NULL, desc); } /*! \brief add a 2-element vector option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddReal2 ( Diderot_Options_t *dopts, const char *name, const char *desc, Diderot_vec2_t *v, bool hasDflt) { char buf[AIR_STRLEN_HUGE] = ""; if (hasDflt) { Diderot_union2_t u; u.v = *v; sprintf(buf, "%lf %lf", (double)(u.r[0]), (double)(u.r[1])); } opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal2); hestOptAdd ( &dopts->hopt, name, "x y", airTypeDouble, 2, 2, odf->hval.r, hasDflt ? buf : NULL, desc); } /*! \brief add a 3-element vector option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddReal3 ( Diderot_Options_t *dopts, const char *name, const char *desc, Diderot_vec3_t *v, bool hasDflt) { char buf[AIR_STRLEN_HUGE] = ""; if (hasDflt) { Diderot_union3_t u; u.v = *v; sprintf(buf, "%lf %lf %lf", (double)(u.r[0]), (double)(u.r[1]), (double)(u.r[2])); } opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal3); hestOptAdd ( &dopts->hopt, name, "x y z", airTypeDouble, 3, 3, odf->hval.r, hasDflt ? buf : NULL, desc); } /*! \brief add a 4-element vector option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddReal4 ( Diderot_Options_t *dopts, const char *name, const char *desc, Diderot_vec4_t *v, bool hasDflt) { char buf[AIR_STRLEN_HUGE] = ""; if (hasDflt) { Diderot_union4_t u; u.v = *v; sprintf(buf, "%lf %lf %lf %lf", (double)(u.r[0]), (double)(u.r[1]), (double)(u.r[2]), (double)(u.r[3])); } opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeReal4); hestOptAdd ( &dopts->hopt, name, "x y z w", airTypeDouble, 4, 4, odf->hval.r, hasDflt ? buf : NULL, desc); } /*! \brief add a string-vauled option to the list of options. * \param dopts the list of options * \param name the name of the option * \param desc a short description string * \param v a pointer to the location where the value gets stored * \param hasDflt true if there is an initial value */ void Diderot_OptAddString ( Diderot_Options_t *dopts, const char *name, const char *desc, char **v, bool hasDflt) { opt_def_t *odf = OptAdd(dopts, name, desc, (void*)v, optTypeString); hestOptAdd ( &dopts->hopt, name, "str", airTypeString, 1, 1, &odf->hval.s, hasDflt ? *v : NULL, desc); } /*! given argc/argv, learn values for all options and set them */ void Diderot_OptProcess (Diderot_Options_t *dopts, int argc, const char **argv) { static const char *me = "Diderot_ProcessOptions"; hestParseOrDie ( dopts->hopt, argc-1, argv+1, dopts->hparm, argv[0], dopts->progInfo ? dopts->progInfo : "(no program info set)", AIR_TRUE, AIR_TRUE, AIR_TRUE); airMopAdd(dopts->mop, dopts->hopt, (airMopper)hestOptFree, airMopAlways); airMopAdd(dopts->mop, dopts->hopt, (airMopper)hestParseFree, airMopAlways); // convert values learned by hest to their Diderot representations for (int i = 0; i < dopts->odefNum; i++) { opt_def_t *odf = dopts->odef[i]; switch (odf->ty) { case optTypeFlag: case optTypeBool: *(bool*)(odf->valp) = odf->hval.b ? true : false; break; case optTypeInt: *(Diderot_int_t *)(odf->valp) = (Diderot_int_t)(odf->hval.i[0]); break; case optTypeReal: *(Diderot_real_t *)(odf->valp) = (Diderot_real_t)(odf->hval.r[0]); break; case optTypeReal2: *(Diderot_vec2_t *)(odf->valp) = vec2((Diderot_real_t)(odf->hval.r[0]), (Diderot_real_t)(odf->hval.r[1])); break; case optTypeReal3: *(Diderot_vec3_t *)(odf->valp) = vec3((Diderot_real_t)(odf->hval.r[0]), (Diderot_real_t)(odf->hval.r[1]), (Diderot_real_t)(odf->hval.r[2])); break; case optTypeReal4: *(Diderot_vec4_t *)(odf->valp) = vec4((Diderot_real_t)(odf->hval.r[0]), (Diderot_real_t)(odf->hval.r[1]), (Diderot_real_t)(odf->hval.r[2]), (Diderot_real_t)(odf->hval.r[3])); break; case optTypeString: { char *s = airStrdup(odf->hval.s); if (s == 0) { fprintf(stderr, "%s: unable to allocate string copy\n", me); exit(1); } *(char **)(odf->valp) = s; } break; default: fprintf(stderr, "%s: unknown option type %d\n", me, odf->ty); exit(1); } /* switch */ } }
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |