/*@@ @file Parameters.c @date Mon Jun 28 21:44:17 1999 @author Tom Goodale @desc Routines to deal with the parameters. @enddesc @version $Header$ @@*/ #include "cctk_Config.h" #include #include #include #include #include "cctk_Flesh.h" #include "SKBinTree.h" #include "cctk_ActiveThorns.h" #include "ParameterBindings.h" #include "cctk_Parameters.h" #include "cctk_Constants.h" #include "cctk_WarnLevel.h" #include "cctk_Misc.h" #include "cctk_Parameter.h" #include "cctk_GNU.h" static char *rcsid="$Header$"; CCTK_FILEVERSION(main_Parameters_c) /******************************************************************** ********************* Local Data Types *********************** ********************************************************************/ /* what is a parameter: * - properties * - data * nothing else! * Props are supposed to be public to thorn programmers, * Data are supposed to be private to flesh! */ typedef struct PARAM { cParamData* props; void* data; } t_param; /* what is a list of parameters: * just a normal linked list... */ typedef struct PARAMLIST { t_param* param; struct PARAMLIST* last; struct PARAMLIST* next; } t_paramlist; /* what is a node of parameter tree * look at it: a list of linked lists... ;-) */ typedef struct PARAMTREENODE { t_paramlist* paramlist; } t_paramtreenode; /******************************************************************** ************************* Static Variables ************************* ********************************************************************/ /* mask for CCTK_ParameterSet() */ static int cctk_parameter_set_mask; /******************************************************************** ********************* Local Routine Prototypes ********************* ********************************************************************/ static t_param *ParameterFind(const char *name, const char *thorn, int scope); static t_param *ParameterNew(const char *thorn, const char *name, const char *type, const char *scope, int steerable, const char *description, const char *defval, void *data); static int ParameterCheck(const char *thorn, const char *name, const char *type, const char *scope, int steerable, const char *description, const char *defval, void *data); static void *ParameterGetSimple (t_param *param, int *type); static int ParameterSetSimple (t_param *param, const char *value); static t_paramtreenode *ParameterPTreeNodeFind(t_sktree *tree, const char *name); #if 0 static t_sktree *ParameterPTreeNodeAdd(t_sktree **tree, const char *name, t_paramtreenode *new_node); #endif static int ParameterGetScope (const char *scope); static int ParameterGetType (const char *type); static int ParameterInsert (t_sktree **tree, t_param *newparam); static int ParameterPrintSimple (t_param *param, const char *format, FILE *file); static int ParameterExtend (t_param *param, const char *range_origin, const char *range, const char *range_description); static int ParameterListAddParam(t_paramlist **paramlist, t_param *newparam); static int ParameterSetKeyword (t_param *param, const char *value); static int ParameterSetString (t_param *param, const char *value); static int ParameterSetSentence (t_param *param, const char *value); static int ParameterSetInteger (t_param *param, const char *value); static int ParameterSetReal (t_param *param, const char *value); static int ParameterSetBoolean (t_param *param, const char *value); /******************************************************************** ********************* Other Routine Prototypes ********************* ********************************************************************/ int CCTK_RegexMatch(const char *string, const char *pattern, const int nmatch, regmatch_t *pmatch); int STR_cmpi(const char *string1, const char *string2); #define STR_CMP(a,b) STR_cmpi(a,b) /******************************************************************** ********************* Local Data ***************************** ********************************************************************/ static t_sktree *paramtree=NULL; /******************************************************************** ********************* External Routines ********************** ********************************************************************/ /*@@ @routine CCTKi_ParameterCreate @date Tue Jun 29 10:08:56 1999 @author Tom Goodale @desc Creates a parameter originating from a thorn/implementation. @enddesc @calls @calledby @history @endhistory @var name @vdesc The name of the parameter @vtype const char * @vio in @vcomment @endvar @var thorn @vdesc The originating thorn @vtype const char * @vio in @vcomment @endvar @var scope @vdesc The scope of the parameter @vtype const char * @vio in @vcomment Private, Restricted, or Global @endvar @var steerable @vdesc Is the parameter steerable ? @vtype int @vio in @vcomment True or false @endvar @var description @vdesc A description of the parameter @vtype const char * @vio in @vcomment @endvar @var defval @vdesc The default value @vtype const char * @vio in @vcomment @endvar @var data @vdesc A pointer to the memory holding the parameter @vtype void * @vio in @vcomment @endvar @returntype int @returndesc 0 on success, -1 on failure to create the parameter -2 if parameter inconsistent @endreturndesc @@*/ int CCTKi_ParameterCreate(const char *name, const char *thorn, const char *type, const char *scope, int steerable, const char *description, const char *defval, void *data, int n_ranges, ...) { int retval; int iscope; int i; t_param *param; va_list ranges; const char *rangeval; const char *rangedesc; iscope = ParameterGetScope(scope); param = ParameterFind(name, thorn, iscope); if(!param) { param = ParameterNew(thorn, name, type, scope, steerable, description, defval, data); if(n_ranges) { va_start(ranges, n_ranges); for(i=0; i < n_ranges; i++) { rangeval = (const char *)va_arg(ranges, const char *); rangedesc = (const char *)va_arg(ranges, const char *); ParameterExtend(param, thorn, rangeval, rangedesc); } va_end(ranges); } retval = ParameterSetSimple(param, defval); } else { retval = ParameterCheck(thorn, name, type, scope, steerable, description, defval, data); } return retval; } /*@@ @routine CCTKi_ParameterAddRange @date Tue Jun 29 10:15:53 1999 @author Tom Goodale @desc Adds a range. Only allowed to add a range if in appropriate scope. @enddesc @calls @calledby @history @endhistory @var origin @vdesc The originating implementation or thorn of the parameter @vtype const char * @vio in @vcomment @endvar @var name @vdesc The name of the parameter @vtype const char * @vio in @vcomment @endvar @var range_origin @vdesc The originating implementation or thorn of the range @vtype const char * @vio in @vcomment @endvar @var range @vdesc The new range @vtype const char * @vio in @vcomment @endvar @var range_description @vdesc A description of the new range @vtype const char * @vio in @vcomment @endvar @returntype int @returndesc 0 on success, A -ve number on failure @endreturndesc @@*/ int CCTKi_ParameterAddRange(const char *implementation, const char *name, const char *range_origin, const char *range, const char *range_description) { int retval; t_param *param; /* For the moment do this in the quick and dirty way 8-( FIXME */ t_sktree *thornlist; t_sktree *node; /*printf("Extending param %s::%s from thorn %s\n", implementation, name, range_origin);*/ thornlist = CCTK_ImpThornList(implementation); retval = -1; if(thornlist) { for(node= SKTreeFindFirst(thornlist); node; node = node->next) { param = ParameterFind(name, node->key, SCOPE_RESTRICTED); if(param) { retval = ParameterExtend(param, range_origin, range, range_description); } else { retval = -1; } } } return retval; } /*@@ @routine CCTK_ParameterSet @date Tue Jun 29 10:22:22 1999 @author Tom Goodale @desc Sets the value (checks for steerable if not initialisation). @enddesc @calls @calledby @history @endhistory @var name @vdesc The name of the parameter @vtype const char * @vio in @vcomment name @endvar @var thorn @vdesc The originating thorn @vtype const char * @vio in @vcomment @endvar @var implementation @vdesc The originating implementation @vtype const char * @vio in @vcomment @endvar @var value @vdesc The value of the parameter @vtype const char * @vio in @vcomment @endvar @returntype int @returndesc negative in case of errors -1 = parameter out of range -2 = parameter not found -3 = trying to steer non steerable parameter @endreturndesc @@*/ int CCTK_ParameterSet(const char *name, const char *thorn, const char *value) { int retval = 0; t_param *param; param = ParameterFind(name, thorn, SCOPE_ANY); if(param) { /* before parameter recovery (which is while parsing the parameter file) all parameters can be set */ if(cctk_parameter_set_mask == PARAMETER_RECOVERY_POST && param->props->steerable != CCTK_STEERABLE_ALWAYS) { /* after parameter recovery only steerable parameters can be set */ CCTK_VWarn(1, __LINE__, __FILE__, "Cactus", "CCTK_ParameterSet: Cannot set parameter '%s::%s' " "(non-steerable)", thorn, name); retval = -3; } else if(cctk_parameter_set_mask == PARAMETER_RECOVERY_IN && param->props->n_set > 0) { /* during parameter recovery STEERABLE_NEVER parameters which were set from the parameter file are overwritten by the checkpoint file */ if (param->props->steerable == CCTK_STEERABLE_NEVER) { CCTK_VWarn(1, __LINE__, __FILE__, "Cactus", "CCTK_ParameterSet: Parameter '%s::%s' " "is non-steerable and will be " "overwritten by its value from the checkpoint file", thorn, name); } else { retval = 1; /* do not restore the original value */ } } else { retval = ParameterSetSimple(param, value); /* register another set operation */ param->props->n_set++; } } else { retval = -2; } return retval; } /*@@ @routine ParameterPrintDescription @date Tue Jun 29 10:24:49 1999 @author Tom Goodale @desc Prints out a description on the given file descriptor with the given format. Should include all data - i.e. ranges, range descriptions, range origins, and default value. @enddesc @calls @calledby @history @endhistory @var name @vdesc The name of the parameter @vtype const char * @vio in @vcomment name @endvar @var thorn @vdesc The originating thorn @vtype const char * @vio in @vcomment @endvar @var implementation @vdesc The originating implementation @vtype const char * @vio in @vcomment @endvar @var format @vdesc The printf format string @vtype const char * @vio in @vcomment This is for each line of the test, and should have one %s in it. @endvar @var file @vdesc File descriptor @vtype FILE * @vio in @vcomment The file to pront out on. @endvar @returntype int @returndesc 1 on success, 0 on failure. @endreturndesc @@*/ int ParameterPrintDescription(const char *name, const char *thorn, const char *format, FILE *file) { int retval; t_param *param; param = NULL; param = ParameterFind(name, thorn, SCOPE_ANY); if(param) { retval = ParameterPrintSimple(param, format, file); } else { retval = -1; } return retval; } /*@@ @routine CCTK_ParameterGet @date Tue Jun 29 10:28:20 1999 @author Tom Goodale @desc Gets the pointer to the parameter - should be used for checkpointing and recovery. @enddesc @calls @calledby @history @endhistory @var name @vdesc The name of the parameter @vtype const char * @vio in @vcomment name @endvar @var thorn @vdesc The originating thorn @vtype const char * @vio in @vcomment @endvar @var implementation @vdesc The originating implementation @vtype const char * @vio in @vcomment @endvar @var type @vdesc The type of the parameter @vtype int * @vio out @vcomment An integer representing the type of the parameter @endvar @returntype void * @returndesc The address of the parameter. @endreturndesc @@*/ void *CCTK_ParameterGet(const char *name, const char *thorn, int *type) { void *retval; t_param *param; param = NULL; param = ParameterFind(name, thorn, SCOPE_ANY); if(param) { retval = ParameterGetSimple(param, type); } else { retval = NULL; } return retval; } /*@@ @routine CCTK_ParameterQueryTimesSet @date Fri July 7 2000 @author Gabrielle Allen @desc Returns the number of times that a parameter has been set, that is if it returns 0 the parameter was not set in a parameter file. @enddesc @calls @calledby @history @endhistory @var name @vdesc The name of the parameter @vtype const char * @vio in @endvar @var thorn @vdesc The originating thorn @vtype const char * @vio in @endvar @returntype int @returndesc Number of times set, negative for error @endreturndesc @@*/ int CCTK_ParameterQueryTimesSet(const char *name, const char *thorn) { int nset; const cParamData *param; param = CCTK_ParameterData (name, thorn); if (param) { nset = param->n_set; } else { nset = -1; } return nset; } /*@@ @routine CCTK_ParameterValString @date Thu Jan 21 2000 @author Thomas Radke @desc Gets the string representation of a parameter's value - should be used for checkpointing and recovery. @enddesc @calls @calledby @history @endhistory @var param_name @vdesc The name of the parameter @vtype const char * @vio in @endvar @var thorn @vdesc The originating thorn @vtype const char * @vio in @endvar @returntype char * @returndesc The address of the allocated string (should be freed after usage). @endreturndesc @@*/ char *CCTK_ParameterValString (const char *param_name, const char *thorn) { int param_type; void *param_data; char *retval = NULL; char buffer [80]; param_data = CCTK_ParameterGet (param_name, thorn, ¶m_type); if (param_data == NULL) return (NULL); switch (param_type) { case PARAMETER_KEYWORD: case PARAMETER_STRING: case PARAMETER_SENTENCE: retval = strdup (*(char **) param_data); break; case PARAMETER_BOOLEAN: retval = strdup ((int) (*(CCTK_INT *) param_data) ? "yes" : "no"); break; case PARAMETER_INT: sprintf (buffer, "%d", (int) (*(CCTK_INT *) param_data)); retval = strdup (buffer); break; case PARAMETER_REAL: sprintf (buffer, "%e", (double) (*(CCTK_REAL *) param_data)); retval = strdup (buffer); break; default: CCTK_VWarn (3, __LINE__, __FILE__, "Cactus", "CCTK_ParameterValString: Unknown type %d for parameter '%s::%s'", param_type, thorn, param_name); retval = NULL; break; } return (retval); } /*@@ @routine CCTK_ParameterWalk @date Tue Jun 29 10:30:21 1999 @author Tom Goodale @desc Gets parameters in order, restricted to ones from 'origin', or all if 'origin' is NULL. Starts with the first parameter if 'first' is true, otherwise gets the next one. Can be used for generating full help file, or for walking the list and checkpointing. @enddesc @calls @calledby @history @endhistory @var first @vdesc Flag to indicate get first parameter or not @vtype int @vio in @vcomment @endvar @var origin @vdesc The origin of this walk @vtype const char * @vio in @vcomment The thorn to walk, or NULL if to walk all params. @endvar @var pfullname @vdesc address of pointer to string where the fullname of the parameter will be stored @vtype char * @vio out @vcomment If not NULL, the full name is written into an allocated string which can be refered to via *pfullname. Should be freed after usage. Full name is "Implementation::name" for global and restricted parameters, and "Thorn::name" for private parameters. @endvar @var pdata @vdesc address of pointer to parameter data structure @vtype cParamData ** @vio out @vcomment If not NULL, the pointer to the parameter data structure is stored in *pdata. @endvar @returntype int @returndesc - zero for success - positive if parameter was not found - negative if initial startpoint was not set @endreturndesc @@*/ int CCTK_ParameterWalk(int first, const char *origin, char **pfullname, const cParamData **pdata) { int return_found; t_sktree *tnode; t_paramtreenode *node; t_paramlist *paramlist; t_param *startpoint; static t_param *prev_startpoint_all = NULL; static t_param *prev_startpoint_thorn = NULL; /* determine the startpoint for search */ if (! first) { startpoint = origin ? prev_startpoint_thorn : prev_startpoint_all; if (startpoint == NULL) { CCTK_Warn(2,__LINE__,__FILE__,"Cactus", "CCTK_ParameterWalk: Cannot walk " "through parameter list without setting a startpoint at first"); return -1; } /* return next match AFTER startpoint */ return_found = 0; } else { /* return next match which also becomes startpoint for following searches */ return_found = 1; startpoint = NULL; } /* iterate over nodes */ for (tnode = SKTreeFindFirst (paramtree) ; tnode ; tnode = tnode->next) { /* get node data */ node = (t_paramtreenode *) tnode->data; /* iterate over parameters in list */ for (paramlist = node->paramlist; paramlist; paramlist = paramlist->next) { /* if startpoint is still unassigned set it to next match in list */ if (startpoint == NULL) { if (! origin || CCTK_Equals (origin, paramlist->param->props->thorn)) startpoint = paramlist->param; } /* Hey, we've found the startpoint ! */ if (startpoint == paramlist->param) { /* Do we have to return this one ? If not prepare finding the next matching param. */ if (return_found) { const char *prefix; if (pfullname) { if (startpoint->props->scope == SCOPE_PRIVATE) prefix = startpoint->props->thorn; else prefix = CCTK_ThornImplementation (startpoint->props->thorn); *pfullname = (char *) malloc (strlen (prefix) + strlen (startpoint->props->name) + 3); sprintf (*pfullname, "%s::%s", prefix, startpoint->props->name); } if (pdata) { *pdata = startpoint->props; } /* save the last startpoint */ prev_startpoint_all = prev_startpoint_thorn = startpoint; return 0; } else { startpoint = NULL; return_found = 1; } } } /* end looping over parameter list */ } /* end looping over all nodes */ return 1; } /**********************************************************************/ /*@@ @routine CCTK_ParameterData @date Tue Aug 31 18:10:46 MSZ 1999 @author Andre Merzky @desc For a given parameter, return description, type and range @enddesc @calls @calledby @history @endhistory @var name @vdesc parameter name @vtype const char * @vio in @vcomment @endvar @var thorn @vdesc thorn parameter belongs to @vtype const char * @vio in @vcomment @endvar @returntype const cParamData * @returndesc pointer to parameter data structure on success, NULL on failure. @endreturndesc @@*/ const cParamData *CCTK_ParameterData (const char *name, const char *thorn) { const cParamData *retval; t_param *param; param = ParameterFind (name, thorn, SCOPE_ANY); if (!param) { retval = NULL; } else { retval = param->props; } return retval; } /******************************************************************** ********************* Local Routines ************************* ********************************************************************/ /*@@ @routine ParameterFind @date Sun Oct 17 16:20:48 1999 @author Tom Goodale @desc Finds a parameter. @enddesc @calls @calledby @history @endhistory @@*/ static t_param *ParameterFind(const char *name, const char *thorn, int scope) { t_param *retval; t_paramtreenode *node; t_paramlist *list; retval = NULL; node = NULL; list = NULL; node = ParameterPTreeNodeFind (paramtree, name); if(node) { for(list = node->paramlist; list; list = list->next) { if(! thorn) { if(list->param->props->scope == SCOPE_GLOBAL) { break; } } else if(scope == SCOPE_ANY) { if(thorn && ! STR_CMP(thorn, list->param->props->thorn)) break; } else if(!STR_CMP(thorn, list->param->props->thorn) && list->param->props->scope == scope) { break; } } } if(list) { retval = list->param; } else { retval = NULL; } return retval; } /*@@ @routine ParameterNew @date Mon Jul 26 10:59:42 1999 @author Tom Goodale @desc Creates a new parameter @enddesc @calls @calledby @history @endhistory @@*/ static t_param *ParameterNew(const char *thorn, const char *name, const char *type, const char *scope, int steerable, const char *description, const char *defval, void *data) { t_param *newparam; char ** stringdata; newparam = (t_param *)malloc(sizeof(t_param)); if(newparam) { newparam->props = (cParamData*) malloc (sizeof (cParamData)); if (newparam->props) { newparam->props->thorn = (char*) malloc (sizeof (char) * (1 + strlen (thorn ))); newparam->props->name = (char*) malloc (sizeof (char) * (1 + strlen (name ))); newparam->props->description = (char*) malloc (sizeof (char) * (1 + strlen (description))); newparam->props->defval = (char*) malloc (sizeof (char) * (1 + strlen (defval ))); newparam->props->scope = ParameterGetScope(scope); newparam->props->type = ParameterGetType(type); newparam->props->steerable = steerable; newparam->props->range = NULL; newparam->props->n_set = 0; newparam->data = data; if(newparam->props->type == PARAMETER_STRING || newparam->props->type == PARAMETER_SENTENCE || newparam->props->type == PARAMETER_KEYWORD) { stringdata = (char **)data; *stringdata = NULL; } if(newparam->props->thorn && newparam->props->name && newparam->props->description && newparam->props->defval) { strcpy(newparam->props->name, name); strcpy(newparam->props->thorn, thorn); strcpy(newparam->props->description, description); strcpy(newparam->props->defval, defval); ParameterInsert(¶mtree, newparam); } } } return newparam; } static int ParameterCheck(const char *thorn, const char *name, const char *type, const char *scope, int steerable, const char *description, const char *defval, void *data) { return -2; } static t_paramtreenode *ParameterPTreeNodeFind(t_sktree *tree, const char *name) { t_sktree *node; t_paramtreenode *retval; node = SKTreeFindNode(tree, name); if(node) { retval = (t_paramtreenode *)(node->data); } else { retval = NULL; } return retval; } #if 0 static t_sktree *ParameterPTreeNodeAdd(t_sktree **tree, const char *name, t_paramtreenode *new_node) { t_sktree *root; root = SKTreeStoreData(*tree, *tree, name, new_node); if(!*tree) { *tree = root; } return root; } #endif static int ParameterGetScope(const char *scope) { int retval; retval = -1; if(!STR_CMP(scope, "GLOBAL")) { retval = SCOPE_GLOBAL; } if(!STR_CMP(scope, "RESTRICTED")) { retval = SCOPE_RESTRICTED; } if(!STR_CMP(scope, "PRIVATE")) { retval = SCOPE_PRIVATE; } return retval; } static int ParameterGetType(const char *type) { int retval; retval = -1; #define PTYPE(x) \ if(!STR_CMP(type, #x)) \ { \ retval = PARAMETER_##x; \ } \ PTYPE(KEYWORD); PTYPE(STRING); PTYPE(SENTENCE); PTYPE(INT); PTYPE(REAL); PTYPE(BOOLEAN); #undef PTYPE if(retval == -1) { fprintf(stderr, "What on earth kind of a parameter is %s ? \n",type); } return retval; } /*@@ @routine ParameterInsert @date Fri Jul 16 10:08:25 1999 @author Tom Goodale @desc @enddesc @calls @calledby @history @endhistory @@*/ static int ParameterInsert(t_sktree **tree, t_param *newparam) { int retval; t_sktree *treenode; t_paramtreenode *node; t_paramlist *list; treenode = SKTreeFindNode(*tree, newparam->props->name); if(treenode) { retval = ParameterListAddParam(&(((t_paramtreenode *)(treenode->data))->paramlist), newparam); } else { node = (t_paramtreenode *)malloc(sizeof(t_paramtreenode)); list = (t_paramlist *)malloc(sizeof(t_paramlist)); if(node && list) { node->paramlist=list; list->param = newparam; list->last=NULL; list->next=NULL; treenode = SKTreeStoreData(*tree, *tree, newparam->props->name, node); if(!*tree) *tree = treenode; retval = 0; } else { retval = -1; free(list); free(node); } } return retval; } /*@@ @routine ParameterGetSimple @date Fri Jul 16 10:07:46 1999 @author Tom Goodale @desc Gets the value of a parameter @enddesc @calls @calledby @history @endhistory @@*/ static void *ParameterGetSimple(t_param *param, int *type) { *type = param->props->type; return param->data; } /*@@ @routine ParameterExtend @date Thu Jul 15 12:55:06 1999 @author Tom Goodale @desc Adds a range to a parameter. @enddesc @calls @calledby @history @endhistory @@*/ static int ParameterExtend(t_param *param, const char *range_origin, const char *range, const char *range_description) { int retcode; int order; t_range *newrange; t_range *rangenode; t_range *lastnode; newrange = (t_range *)malloc(sizeof(t_range)); if(newrange) { newrange->range = (char *)malloc(sizeof(char)*(1+strlen(range))); newrange->origin = (char *)malloc(sizeof(char)*(1+strlen(range_origin))); newrange->description = (char *)malloc(sizeof(char)*(1+strlen(range_description))); } if(newrange && newrange->range && newrange->origin && newrange->description) { /* Fill out the data */ newrange->last = NULL; newrange->next = NULL; newrange->active = 0; strcpy(newrange->range, range); strcpy(newrange->origin, range_origin); strcpy(newrange->description, range_description); lastnode = NULL; /* Search the list for the right place to insert it. */ for(rangenode=param->props->range; rangenode; rangenode=rangenode->next) { lastnode = rangenode; order = STR_CMP(range_origin, rangenode->origin); if(order <= 0) { /* Insert before this node */ newrange->next=rangenode; newrange->last=rangenode->last; rangenode->last=newrange; if(param->props->range == rangenode) param->props->range=newrange; if(newrange->last) newrange->last->next = newrange; break; } } if(!rangenode) { /* Insert at the end of the list */ newrange->next=NULL; newrange->last=lastnode; if(param->props->range == NULL) param->props->range=newrange; if(newrange->last) newrange->last->next = newrange; } retcode = 0; } else { retcode = -1; } return retcode; } static int ParameterSetSimple(t_param *param, const char *value) { int retval; retval = -2; /* fprintf(stdout, "Setting value of parameter %s::%s\n", param->props->thorn, param->props->name);*/ switch(param->props->type) { case PARAMETER_KEYWORD : retval = ParameterSetKeyword(param, value); break; case PARAMETER_STRING : retval = ParameterSetString(param, value); break; case PARAMETER_SENTENCE : retval = ParameterSetSentence(param, value); break; case PARAMETER_INT : retval = ParameterSetInteger(param, value); break; case PARAMETER_REAL : retval = ParameterSetReal(param, value); break; case PARAMETER_BOOLEAN : retval = ParameterSetBoolean(param, value); break; default : fprintf(stderr, "Unknown parameter type %d\n", param->props->type); } return retval; } static int ParameterPrintSimple(t_param *param, const char *format, FILE *file) { t_range *range; fprintf(file, format, "Parameter", param->props->name); fprintf(file, format, "Thorn", param->props->thorn); fprintf(file, format, "Desc", param->props->description); fprintf(file, format, "Def", param->props->defval); for(range=param->props->range; range; range=range->next) { fprintf(file, format, "Range:", range->range); } return 0; } static int ParameterListAddParam(t_paramlist **paramlist, t_param *newparam) { int retval; t_paramlist *node; node = (t_paramlist *)malloc(sizeof(t_paramlist)); if(node) { node->param = newparam; /* Place at beginning of list for now. */ node->next = *paramlist; node->last = NULL; (*paramlist)->last = node; *paramlist = node; retval = 0; } else { retval = 1; } return retval; } static int ParameterSetKeyword(t_param *param, const char *value) { int retval; t_range *range; retval = -1; for(range = param->props->range; range ; range = range->next) { if(CCTK_IsThornActive(range->origin)||CCTK_Equals(param->props->thorn, range->origin)) { if(!STR_CMP(value, range->range)) { retval = CCTK_SetString(param->data, value); break; } } } if(retval == -1) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "ParameterSetKeyword: Unable to set keyword %s::%s - %s not in any active range", param->props->thorn, param->props->name, value); if(*((char **)param->data) == NULL) { fprintf(stderr, "Since this was the default value, setting anyway - please fix!\n"); CCTK_SetString(param->data, value); } } return retval; } static int ParameterSetString(t_param *param, const char *value) { int retval; t_range *range; retval = -1; for(range = param->props->range; range ; range = range->next) { if(CCTK_IsThornActive(range->origin)||CCTK_Equals(param->props->thorn, range->origin)) { #ifndef CCTK_PARAMUNCHECKED if(CCTK_RegexMatch(value, range->range, 0, NULL)) { #endif retval = CCTK_SetString(param->data, value); break; #ifndef CCTK_PARAMUNCHECKED } #endif } } if(retval == -1) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "ParameterSetString: Unable to set string %s::%s - %s not in any active range", param->props->thorn, param->props->name, value); if(*((char **)param->data) == NULL) { fprintf(stderr, "Since this was the default value, setting anyway - please fix!\n"); CCTK_SetString(param->data, value); } } return retval; } static int ParameterSetSentence(t_param *param, const char *value) { int retval; t_range *range; retval = -1; for(range = param->props->range; range ; range = range->next) { if(CCTK_IsThornActive(range->origin)||CCTK_Equals(param->props->thorn, range->origin)) { #ifndef CCTK_PARAMUNCHECKED if(CCTK_RegexMatch(value, range->range, 0, NULL)) { #endif retval = CCTK_SetString(param->data, value); break; #ifndef CCTK_PARAMUNCHECKED } #endif } } if(retval == -1) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "ParameterSetSentance: Unable to set sentance %s::%s - %s not in any active range", param->props->thorn, param->props->name, value); if(*((char **)param->data) == NULL) { fprintf(stderr, "Since this was the default value, setting anyway - please fix!\n"); CCTK_SetString(param->data, value); } } return retval; } static int ParameterSetInteger(t_param *param, const char *value) { int retval; t_range *range; int inval; CCTK_INT *val; inval = strtol(value,NULL,0); val = (CCTK_INT *)param->data; retval = -1; for(range = param->props->range; range ; range = range->next) { if(CCTK_IsThornActive(range->origin)||CCTK_Equals(param->props->thorn, range->origin)) { #ifndef CCTK_PARAMUNCHECKED if(Util_IntInRange(inval, range->range)) { #endif *val = inval; retval = 0; break; #ifndef CCTK_PARAMUNCHECKED } #endif } } if(retval == -1) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "ParameterSetInteger: Unable to set integer %s::%s - %s not in any active range", param->props->thorn, param->props->name, value); } return retval; } static int ParameterSetReal(t_param *param, const char *value) { int retval,p; t_range *range; double inval; CCTK_REAL *val; char temp[1001]; /* Convert the value string to a double. Allow various formats.*/ strncpy(temp, value, 1000); for (p=0;pdata; retval = -1; for(range = param->props->range; range ; range = range->next) { if(CCTK_IsThornActive(range->origin)||CCTK_Equals(param->props->thorn, range->origin)) { #ifndef CCTK_PARAMUNCHECKED if(Util_DoubleInRange(inval, range->range)) { #endif *val = inval; retval = 0; break; #ifndef CCTK_PARAMUNCHECKED } #endif } } if(retval == -1) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "ParameterSetReal: Unable to set real %s::%s - %s not in any active range", param->props->thorn, param->props->name, value); } return retval; } static int ParameterSetBoolean(t_param *param, const char *value) { int retval; retval = -1; retval = CCTK_SetBoolean(param->data, value); if(retval == -1) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "ParameterSetBoolean: Unable to set boolean %s::%s - %s not recognised", param->props->thorn, param->props->name, value); } return retval; } void CCTKi_SetParameterSetMask(int mask) { cctk_parameter_set_mask = mask; } /*#define TEST_PARAMETERS*/ #ifdef TEST_PARAMETERS struct { int a; char *foo; double beta; } params; int main(void) { CCTKi_ParameterCreate("a", "thorn1", "imp1", "int", "global", 0, "The a param", "2", &(params.a)); CCTKi_ParameterCreate("foo", "thorn2", "imp2", "keyword", "private", 0, "The foo param", "bingo", &(params.foo)); printf("Testing thorn,null\n"); ParameterPrintDescription("a", "thorn1", /*const char *thorn,*/ NULL, /* const char *implementation,*/ "..%s..%s\n",/* const char *format,*/ stdout); printf("Testing null,imp\n"); ParameterPrintDescription("a", NULL, /*const char *thorn,*/ "imp1", /* const char *implementation,*/ "..%s..%s\n",/* const char *format,*/ stdout); printf("Testing thorn,thorn\n"); ParameterPrintDescription("a", "thorn1", /*const char *thorn,*/ "thorn1", /* const char *implementation,*/ "..%s..%s\n",/* const char *format,*/ stdout); printf("Testing imp,imp\n"); ParameterPrintDescription("a", "imp1", /*const char *thorn,*/ "imp1", /* const char *implementation,*/ "..%s..%s\n",/* const char *format,*/ stdout); printf("Testing imp,null\n"); ParameterPrintDescription("a", "imp1", /*const char *thorn,*/ NULL, /* const char *implementation,*/ "..%s..%s\n",/* const char *format,*/ stdout); printf("Adding a range to a\n"); ParameterAddRange("imp1", "a", "imp1", "1:7:0", "A nice range for a"); printf("Adding another range to a\n"); ParameterAddRange("imp1", "a", "imp1", "1:7:1", "Another nice range for a"); printf("a is now\n"); ParameterPrintDescription("a", "thorn1", /*const char *thorn,*/ NULL, /* const char *implementation,*/ "..%s..%s\n",/* const char *format,*/ stdout); return 0; } #endif