8 #include "PVParams.hpp" 9 #include "include/pv_common.h" 10 #include "utils/PVAlloc.hpp" 22 #define PARAMETERARRAY_INITIALSIZE 8 23 #define PARAMETERARRAYSTACK_INITIALCOUNT 5 24 #define PARAMETERSTRINGSTACK_INITIALCOUNT 5 25 #define PARAMETERSWEEP_INCREMENTCOUNT 10 40 int pv_parseParameters(
PV::PVParams *action_handler,
const char *paramBuffer,
size_t len);
43 #define INITIALNUMGROUPS 20 // maximum number of groups 45 PV_Stream pvstream = PV_fopen(
"parser/params.txt",
"r",
false);
49 pv_parseParameters(handler);
65 Parameter::Parameter(
const char *name,
double value) {
66 paramName = strdup(name);
67 paramValue = (float)value;
68 paramDblValue = value;
69 hasBeenReadFlag =
false;
72 Parameter::~Parameter() { free(paramName); }
74 ParameterArray::ParameterArray(
int initialSize) {
75 hasBeenReadFlag =
false;
77 paramName = strdup(
"Unnamed Parameter array");
78 bufferSize = initialSize;
82 values = (
float *)calloc(bufferSize,
sizeof(
float));
83 valuesDbl = (
double *)calloc(bufferSize,
sizeof(
double));
84 if (values == NULL || valuesDbl == NULL) {
85 Fatal().printf(
"ParameterArray failed to allocate memory for \"%s\"\n", name());
90 ParameterArray::~ParameterArray() {
99 int ParameterArray::setName(
const char *name) {
100 int status = PV_SUCCESS;
101 if (paramNameSet ==
false) {
103 paramName = strdup(name);
108 "ParameterArray::setName called with \"%s\" but name is already set to \"%s\"\n",
116 int ParameterArray::pushValue(
double value) {
117 assert(bufferSize >= arraySize);
118 if (bufferSize == arraySize) {
119 bufferSize += PARAMETERARRAY_INITIALSIZE;
120 float *new_values = (
float *)calloc(bufferSize,
sizeof(
float));
121 if (new_values == NULL) {
123 "ParameterArray::pushValue failed to increase array \"%s\" to %d values\n",
127 memcpy(new_values, values,
sizeof(
float) * arraySize);
130 double *new_values_dbl = (
double *)calloc(bufferSize,
sizeof(
double));
131 if (new_values == NULL) {
133 "ParameterArray::pushValue failed to increase array \"%s\" to %d values\n",
137 memcpy(new_values_dbl, valuesDbl,
sizeof(
double) * arraySize);
139 valuesDbl = new_values_dbl;
141 assert(arraySize < bufferSize);
142 valuesDbl[arraySize] = value;
143 values[arraySize] = (float)value;
148 ParameterArray *ParameterArray::copyParameterArray() {
149 ParameterArray *returnPA =
new ParameterArray(bufferSize);
150 int status = returnPA->setName(paramName);
151 assert(status == PV_SUCCESS);
152 for (
int i = 0; i < arraySize; i++) {
153 returnPA->pushValue(valuesDbl[i]);
162 ParameterString::ParameterString(
const char *name,
const char *value) {
163 paramName = name ? strdup(name) : NULL;
164 paramValue = value ? strdup(value) : NULL;
165 hasBeenReadFlag =
false;
168 ParameterString::~ParameterString() {
177 this->maxCount = maxCount;
182 ParameterStack::~ParameterStack() {
183 for (
int i = 0; i < count; i++) {
184 delete parameters[i];
193 assert(count < maxCount);
194 parameters[count++] = param;
200 return parameters[count--];
203 ParameterArrayStack::ParameterArrayStack(
int initialCount) {
204 allocation = initialCount;
206 parameterArrays = NULL;
207 if (initialCount > 0) {
209 if (parameterArrays == NULL) {
211 "ParameterArrayStack unable to allocate %d parameter arrays\n", initialCount);
216 ParameterArrayStack::~ParameterArrayStack() {
217 for (
int k = 0; k < count; k++) {
218 delete parameterArrays[k];
219 parameterArrays[k] = NULL;
221 free(parameterArrays);
222 parameterArrays = NULL;
226 assert(count <= allocation);
227 if (count == allocation) {
228 int newallocation = allocation + RESIZE_ARRAY_INCR;
231 if (!newParameterArrays)
233 for (
int i = 0; i < count; i++) {
234 newParameterArrays[i] = parameterArrays[i];
236 allocation = newallocation;
237 free(parameterArrays);
238 parameterArrays = newParameterArrays;
240 assert(count < allocation);
241 parameterArrays[count] = array;
249 ParameterStringStack::ParameterStringStack(
int initialCount) {
250 allocation = initialCount;
255 ParameterStringStack::~ParameterStringStack() {
256 for (
int i = 0; i < count; i++) {
257 delete parameterStrings[i];
259 free(parameterStrings);
266 assert(count <= allocation);
267 if (count == allocation) {
268 int newallocation = allocation + RESIZE_ARRAY_INCR;
271 if (!newparameterStrings)
273 for (
int i = 0; i < count; i++) {
274 newparameterStrings[i] = parameterStrings[i];
276 allocation = newallocation;
277 free(parameterStrings);
278 parameterStrings = newparameterStrings;
280 assert(count < allocation);
281 parameterStrings[count++] = param;
287 return parameterStrings[count--];
293 const char *ParameterStringStack::lookup(
const char *targetname) {
294 const char *result = NULL;
295 for (
int i = 0; i < count; i++) {
296 if (!strcmp(parameterStrings[i]->getName(), targetname)) {
297 result = parameterStrings[i]->getValue();
309 ParameterGroup::ParameterGroup(
315 this->groupName = strdup(name);
316 this->groupKeyword = NULL;
318 this->arrayStack = array_stack;
319 this->stringStack = string_stack;
320 this->processRank = rank;
323 ParameterGroup::~ParameterGroup() {
336 int ParameterGroup::setGroupKeyword(
const char *keyword) {
337 if (groupKeyword == NULL) {
338 size_t keywordlen = strlen(keyword);
339 groupKeyword = (
char *)malloc(keywordlen + 1);
341 strcpy(groupKeyword, keyword);
344 return groupKeyword == NULL ? PV_FAILURE : PV_SUCCESS;
348 this->stringStack = stringStack;
354 return stringStack == NULL ? PV_FAILURE : PV_SUCCESS;
360 int ParameterGroup::present(
const char *name) {
361 int count = stack->size();
362 for (
int i = 0; i < count; i++) {
364 if (strcmp(name, p->name()) == 0) {
374 double ParameterGroup::value(
const char *name) {
375 int count = stack->size();
376 for (
int i = 0; i < count; i++) {
378 if (strcmp(name, p->name()) == 0) {
383 "PVParams::ParameterGroup::value: ERROR, couldn't find a value for %s" 390 bool ParameterGroup::arrayPresent(
const char *name) {
391 bool array_found =
false;
392 int count = arrayStack->size();
393 for (
int i = 0; i < count; i++) {
395 if (strcmp(name, p->name()) == 0) {
400 if (!array_found) { array_found = (present(name) != 0); }
404 const float *ParameterGroup::arrayValues(
const char *name,
int *size) {
405 int count = arrayStack->size();
407 const float *v = NULL;
409 for (
int i = 0; i < count; i++) {
410 p = arrayStack->peek(i);
411 if (strcmp(name, p->name()) == 0) {
412 v = p->getValues(size);
418 for (
int i = 0; i < stack->size(); i++) {
421 if (strcmp(name, q1->name()) == 0) {
434 const double *ParameterGroup::arrayValuesDbl(
const char *name,
int *size) {
435 int count = arrayStack->size();
437 const double *v = NULL;
439 for (
int i = 0; i < count; i++) {
440 p = arrayStack->peek(i);
441 if (strcmp(name, p->name()) == 0) {
442 v = p->getValuesDbl(size);
448 for (
int i = 0; i < stack->size(); i++) {
451 if (strcmp(name, q1->name()) == 0) {
457 v = q->valueDblPtr();
464 int ParameterGroup::stringPresent(
const char *stringName) {
470 int count = stringStack->size();
471 for (
int i = 0; i < count; i++) {
474 if (!strcmp(stringName, pstr->getName())) {
481 const char *ParameterGroup::stringValue(
const char *stringName) {
484 int count = stringStack->size();
485 for (
int i = 0; i < count; i++) {
488 if (!strcmp(stringName, pstr->getName())) {
489 return pstr->getValue();
495 int ParameterGroup::warnUnread() {
496 int status = PV_SUCCESS;
498 count = stack->size();
499 for (
int i = 0; i < count; i++) {
501 if (!p->hasBeenRead()) {
502 if (processRank == 0)
504 "Parameter group \"%s\": parameter \"%s\" has not been read.\n",
510 count = arrayStack->size();
511 for (
int i = 0; i < count; i++) {
513 if (!parr->hasBeenRead()) {
514 if (processRank == 0)
516 "Parameter group \"%s\": array parameter \"%s\" has not been read.\n",
521 count = stringStack->size();
522 for (
int i = 0; i < count; i++) {
524 if (!pstr->hasBeenRead()) {
525 if (processRank == 0)
527 "Parameter group \"%s\": string parameter \"%s\" has not been read.\n",
536 bool ParameterGroup::hasBeenRead(
const char *paramName) {
538 count = stack->size();
539 for (
int i = 0; i < count; i++) {
541 if (!strcmp(p->name(), paramName)) {
542 return p->hasBeenRead();
545 count = arrayStack->size();
546 for (
int i = 0; i < count; i++) {
548 if (!strcmp(parr->name(), paramName)) {
549 return parr->hasBeenRead();
552 count = stringStack->size();
553 for (
int i = 0; i < count; i++) {
555 if (!strcmp(pstr->getName(), paramName)) {
556 return pstr->hasBeenRead();
562 int ParameterGroup::clearHasBeenReadFlags() {
563 int status = PV_SUCCESS;
564 int count = stack->size();
565 for (
int i = 0; i < count; i++) {
567 p->clearHasBeenRead();
569 count = arrayStack->size();
570 for (
int i = 0; i < count; i++) {
572 parr->clearHasBeenRead();
574 count = stringStack->size();
575 for (
int i = 0; i < count; i++) {
577 pstr->clearHasBeenRead();
582 int ParameterGroup::pushNumerical(
Parameter *param) {
return stack->
push(param); }
584 int ParameterGroup::pushString(
ParameterString *param) {
return stringStack->push(param); }
586 int ParameterGroup::setValue(
const char *param_name,
double value) {
587 int status = PV_SUCCESS;
588 int count = stack->size();
589 for (
int i = 0; i < count; i++) {
591 if (strcmp(param_name, p->name()) == 0) {
597 "PVParams::ParameterGroup::setValue: ERROR, couldn't find parameter %s" 598 " in group \"%s\"\n",
605 int ParameterGroup::setStringValue(
const char *param_name,
const char *svalue) {
606 int status = PV_SUCCESS;
607 int count = stringStack->size();
608 for (
int i = 0; i < count; i++) {
610 if (strcmp(param_name, p->getName()) == 0) {
616 "PVParams::ParameterGroup::setStringValue: ERROR, couldn't find a string value for %s" 617 " in group \"%s\"\n",
629 for (
int i = 0; i < stack->size(); i++) {
630 returnStack->
push(stack->peek(i)->copyParameter());
640 for (
int i = 0; i < arrayStack->size(); i++) {
641 returnStack->push(arrayStack->peek(i)->copyParameterArray());
651 for (
int i = 0; i < stringStack->size(); i++) {
652 returnStack->push(stringStack->peek(i)->copyParameterString());
657 ParameterSweep::ParameterSweep() {
661 currentBufferSize = 0;
667 ParameterSweep::~ParameterSweep() {
674 if (valuesString != NULL) {
675 for (
int k = 0; k < numValues; k++) {
676 free(valuesString[k]);
683 int ParameterSweep::setGroupAndParameter(
const char *groupname,
const char *parametername) {
684 int status = PV_SUCCESS;
685 if (groupName != NULL || paramName != NULL) {
686 ErrorLog(errorMessage);
687 errorMessage.printf(
"ParameterSweep::setGroupParameter: ");
688 if (groupName != NULL) {
689 errorMessage.printf(
" groupName has already been set to \"%s\".", groupName);
691 if (paramName != NULL) {
692 errorMessage.printf(
" paramName has already been set to \"%s\".", paramName);
694 errorMessage.printf(
"\n");
698 groupName = strdup(groupname);
699 paramName = strdup(parametername);
705 int ParameterSweep::pushNumericValue(
double val) {
706 int status = PV_SUCCESS;
707 if (numValues == 0) {
710 assert(type == SWEEP_NUMBER);
711 assert(valuesString == NULL);
713 assert(numValues <= currentBufferSize);
714 if (numValues == currentBufferSize) {
715 currentBufferSize += PARAMETERSWEEP_INCREMENTCOUNT;
716 double *newValuesNumber = (
double *)calloc(currentBufferSize,
sizeof(
double));
717 if (newValuesNumber == NULL) {
718 ErrorLog().printf(
"ParameterSweep:pushNumericValue: unable to allocate memory\n");
722 for (
int k = 0; k < numValues; k++) {
723 newValuesNumber[k] = valuesNumber[k];
726 valuesNumber = newValuesNumber;
728 valuesNumber[numValues] = val;
733 int ParameterSweep::pushStringValue(
const char *sval) {
734 int status = PV_SUCCESS;
735 if (numValues == 0) {
738 assert(type == SWEEP_STRING);
739 assert(valuesNumber == NULL);
741 assert(numValues <= currentBufferSize);
742 if (numValues == currentBufferSize) {
743 currentBufferSize += PARAMETERSWEEP_INCREMENTCOUNT;
744 char **newValuesString = (
char **)calloc(currentBufferSize,
sizeof(
char *));
745 if (newValuesString == NULL) {
746 ErrorLog().printf(
"ParameterSweep:pushStringValue: unable to allocate memory\n");
750 for (
int k = 0; k < numValues; k++) {
751 newValuesString[k] = valuesString[k];
754 valuesString = newValuesString;
756 valuesString[numValues] = strdup(sval);
761 int ParameterSweep::getNumericValue(
int n,
double *val) {
762 int status = PV_SUCCESS;
763 assert(valuesNumber != NULL);
764 if (type != SWEEP_NUMBER || n < 0 || n >= numValues) {
768 *val = valuesNumber[n];
773 const char *ParameterSweep::getStringValue(
int n) {
775 assert(valuesString != NULL);
776 if (type == SWEEP_STRING && n >= 0 && n < numValues) {
777 str = valuesString[n];
787 PVParams::PVParams(
const char *filename,
size_t initialSize,
Communicator *inIcComm) {
788 this->icComm = inIcComm;
789 initialize(initialSize);
797 PVParams::PVParams(
size_t initialSize,
Communicator *inIcComm) {
798 this->icComm = inIcComm;
799 initialize(initialSize);
810 long int bufferLength,
813 this->icComm = inIcComm;
814 initialize(initialSize);
815 parseBuffer(buffer, bufferLength);
818 PVParams::~PVParams() {
819 for (
int i = 0; i < numGroups; i++) {
823 delete currentParamArray;
824 currentParamArray = NULL;
828 delete this->activeParamSweep;
829 for (
int i = 0; i < numParamSweeps; i++) {
830 delete paramSweeps[i];
839 int PVParams::initialize(
size_t initialSize) {
841 groupArraySize = initialSize;
843 MPI_Comm_rank(icComm->globalCommunicator(), &worldRank);
844 MPI_Comm_size(icComm->globalCommunicator(), &worldSize);
851 currentParamArray =
new ParameterArray(PARAMETERARRAYSTACK_INITIALCOUNT);
855 newActiveParamSweep();
859 debugParsing =
false;
860 #endif // DEBUG_PARSING 863 return (groups && stack && stringStack && activeParamSweep) ? PV_SUCCESS : PV_FAILURE;
866 int PVParams::newActiveParamSweep() {
867 int status = PV_SUCCESS;
869 if (activeParamSweep == NULL) {
870 Fatal().printf(
"PVParams::newActiveParamSweep: unable to create activeParamSweep");
876 int PVParams::parseFile(
const char *filename) {
878 char *paramBuffer =
nullptr;
880 if (worldRank == rootproc) {
881 std::string paramBufferString(
"");
882 loadParamBuffer(filename, paramBufferString);
883 bufferlen = paramBufferString.size();
885 paramBuffer = (
char *)pvMalloc(bufferlen + 1);
886 memcpy(paramBuffer, paramBufferString.c_str(), bufferlen);
887 paramBuffer[bufferlen] =
'\0';
891 for (
int i = 0; i < sz; i++) {
894 MPI_Send(paramBuffer, (
int)bufferlen, MPI_CHAR, i, 31, icComm->globalCommunicator());
900 MPI_Status mpi_status;
902 MPI_Probe(rootproc, 31, icComm->globalCommunicator(), &mpi_status);
904 MPI_Get_count(&mpi_status, MPI_CHAR, &count);
905 bufferlen = (size_t)count;
906 paramBuffer = (
char *)malloc(bufferlen);
907 if (paramBuffer == NULL) {
909 "PVParams::parseFile: Rank %d process unable to allocate memory for params buffer\n",
918 icComm->globalCommunicator(),
923 int status = parseBuffer(paramBuffer, bufferlen);
928 void PVParams::loadParamBuffer(
char const *filename, std::string ¶msFileString) {
929 if (filename ==
nullptr) {
930 Fatal() <<
"PVParams::loadParamBuffer: filename is null\n";
932 struct stat filestatus;
933 if (PV_stat(filename, &filestatus)) {
935 "PVParams::parseFile unable to get status of file \"%s\": %s\n",
939 if (filestatus.st_mode & S_IFDIR) {
940 Fatal().printf(
"PVParams::parseFile: specified file \"%s\" is a directory.\n", filename);
944 char const *
const luaext =
".lua";
945 size_t const luaextlen = strlen(luaext);
946 size_t const fnlen = strlen(filename);
947 bool const useLua = fnlen >= luaextlen && !strcmp(&filename[fnlen - luaextlen], luaext);
949 bool const useLua =
false;
954 InfoLog() <<
"Running lua program \"" << filename <<
"\".\n";
955 lua_State *lua_state = luaL_newstate();
956 luaL_openlibs(lua_state);
957 int result = luaL_dofile(lua_state, filename);
958 if (result != LUA_OK) {
959 char const *errorMessage = lua_tostring(lua_state, -1);
960 lua_pop(lua_state, 1);
961 Fatal() << errorMessage;
963 lua_getglobal(lua_state,
"paramsFileString");
965 char const *lstring = lua_tolstring(lua_state, -1, &llength);
966 if (lstring ==
nullptr) {
967 Fatal() <<
"Lua program \"" << filename
968 <<
"\" does not create a string variable \"paramsFileString\".\n";
970 paramsFileString.insert(paramsFileString.end(), lstring, &lstring[llength]);
971 lua_pop(lua_state, 1);
972 lua_close(lua_state);
973 InfoLog() <<
"Retrieved paramsFileString, with length " << llength <<
".\n";
977 off_t sz = filestatus.st_size;
978 std::ifstream paramsStream(filename, std::ios_base::in);
979 if (paramsStream.fail()) {
982 paramsFileString.resize(sz);
983 paramsStream.read(¶msFileString[0], sz);
987 bool PVParams::hasSweepValue(
const char *inParamName) {
989 const char *group_name;
990 for (
int k = 0; k < numberOfParameterSweeps(); k++) {
992 group_name = sweep->getGroupName();
993 const char *param_name = sweep->getParamName();
997 "PVParams::hasSweepValue error: ParameterSweep %d (zero-indexed) refers to " 998 "non-existent group \"%s\"\n",
1002 if (!strcmp(gp->getGroupKeyword(),
"HyPerCol") && !strcmp(param_name, inParamName)) {
1010 int PVParams::parseBuffer(
char const *buffer,
long int bufferLength) {
1014 parseStatus = pv_parseParameters(
this, buffer, bufferLength);
1015 if (parseStatus != 0) {
1017 "Rank %d process: pv_parseParameters failed with return value %d\n",
1021 getOutputStream().flush();
1023 setParameterSweepSize();
1031 if (numberOfParameterSweeps() > 0) {
1032 if (!hasSweepValue(
"outputPath")) {
1033 const char *hypercolgroupname = NULL;
1034 const char *outputPathName = NULL;
1035 for (
int g = 0; g < numGroups; g++) {
1036 if (groups[g]->getGroupKeyword(),
"HyPerCol") {
1037 hypercolgroupname = groups[g]->name();
1038 outputPathName = groups[g]->stringValue(
"outputPath");
1039 if (outputPathName == NULL) {
1041 "PVParams::outputPath must be specified if parameterSweep does " 1042 "not sweep over outputPath\n");
1047 if (hypercolgroupname == NULL) {
1048 ErrorLog().printf(
"PVParams::parseBuffer: no HyPerCol group\n");
1053 int lenserialno = snprintf(&dummy, 0,
"%d", parameterSweepSize - 1);
1057 "%s/paramsweep_%0*d/",
1060 parameterSweepSize - 1)
1062 char *outputPathStr = (
char *)calloc(len,
sizeof(
char));
1063 if (outputPathStr == NULL)
1065 for (
int i = 0; i < parameterSweepSize; i++) {
1066 int chars_needed = snprintf(
1067 outputPathStr, len,
"%s/paramsweep_%0*d/", outputPathName, lenserialno, i);
1068 assert(chars_needed < len);
1069 activeParamSweep->pushStringValue(outputPathStr);
1071 free(outputPathStr);
1072 outputPathStr = NULL;
1073 addActiveParamSweep(hypercolgroupname,
"outputPath");
1076 if (!hasSweepValue(
"checkpointWriteDir")) {
1077 const char *hypercolgroupname = NULL;
1078 const char *checkpointWriteDir = NULL;
1079 for (
int g = 0; g < numGroups; g++) {
1080 if (groups[g]->getGroupKeyword(),
"HyPerCol") {
1081 hypercolgroupname = groups[g]->name();
1082 checkpointWriteDir = groups[g]->stringValue(
"checkpointWriteDir");
1087 if (hypercolgroupname == NULL) {
1088 ErrorLog().printf(
"PVParams::parseBuffer: no HyPerCol group\n");
1091 if (checkpointWriteDir) {
1093 int lenserialno = snprintf(&dummy, 0,
"%d", parameterSweepSize - 1);
1097 "%s/paramsweep_%0*d/",
1100 parameterSweepSize - 1)
1102 char *checkpointPathStr = (
char *)calloc(len,
sizeof(
char));
1103 if (checkpointPathStr == NULL)
1105 for (
int i = 0; i < parameterSweepSize; i++) {
1106 int chars_needed = snprintf(
1109 "%s/paramsweep_%0*d/",
1113 assert(chars_needed < len);
1114 activeParamSweep->pushStringValue(checkpointPathStr);
1116 free(checkpointPathStr);
1117 checkpointPathStr = NULL;
1118 addActiveParamSweep(hypercolgroupname,
"checkpointWriteDir");
1123 if (icComm->numCommBatches() > 1) {
1125 for (
int g = 0; g < numGroups; g++) {
1127 if (!strcmp(group->getGroupKeyword(),
"HyPerCol")) {
1128 hypercolGroup = group;
1132 FatalIf(hypercolGroup ==
nullptr,
"PVParams::parseBuffer: no HyPerCol group\n");
1137 for (
int k = 0; k < numberOfParameterSweeps(); k++) {
1139 const char *group_name = sweep->getGroupName();
1140 const char *param_name = sweep->getParamName();
1141 SweepType type = sweep->getType();
1144 ErrorLog().printf(
"ParameterSweep: there is no group \"%s\"\n", group_name);
1149 if (!g->present(param_name)) {
1151 g->pushNumerical(p);
1155 if (!g->stringPresent(param_name)) {
1160 default: assert(0);
break;
1164 clearHasBeenReadFlags();
1171 void PVParams::ioParamValue<int>(
1172 enum ParamsIOFlag ioFlag,
1173 const char *groupName,
1174 const char *paramName,
1177 bool warnIfAbsent) {
1179 case PARAMS_IO_READ:
1180 *paramValue = valueInt(groupName, paramName, defaultValue, warnIfAbsent);
1182 case PARAMS_IO_WRITE: writeParam(paramName, *paramValue);
break;
1187 void PVParams::ioParamValueRequired<int>(
1188 enum ParamsIOFlag ioFlag,
1189 const char *groupName,
1190 const char *paramName,
1193 case PARAMS_IO_READ: *paramValue = valueInt(groupName, paramName);
break;
1194 case PARAMS_IO_WRITE: writeParam(paramName, *paramValue);
break;
1198 int PVParams::setParameterSweepSize() {
1199 parameterSweepSize = -1;
1200 for (
int k = 0; k < this->numberOfParameterSweeps(); k++) {
1201 if (parameterSweepSize < 0) {
1202 parameterSweepSize = this->paramSweeps[k]->getNumValues();
1205 if (parameterSweepSize != this->paramSweeps[k]->getNumValues()) {
1207 "PVParams::setParameterSweepSize: all ParameterSweeps in the " 1208 "parameters file must have the same number of entries.\n");
1213 if (parameterSweepSize < 0)
1214 parameterSweepSize = 0;
1215 return parameterSweepSize;
1218 int PVParams::setParameterSweepValues(
int n) {
1219 int status = PV_SUCCESS;
1221 if (n < 0 || n >= parameterSweepSize) {
1222 status = PV_FAILURE;
1225 for (
int k = 0; k < this->numberOfParameterSweeps(); k++) {
1227 SweepType type = paramSweep->getType();
1228 const char *group_name = paramSweep->getGroupName();
1229 const char *param_name = paramSweep->getParamName();
1237 paramSweep->getNumericValue(n, &v);
1238 gp->setValue(param_name, v);
1241 s = paramSweep->getStringValue(n);
1242 gp->setStringValue(param_name, s);
1244 default: assert(0);
break;
1257 if (worldRank == 0) {
1258 ErrorLog().printf(
"PVParams::present: couldn't find a group for %s\n", groupName);
1263 return g->present(paramName);
1273 if (worldRank == 0) {
1274 ErrorLog().printf(
"PVParams::value: ERROR, couldn't find a group for %s\n", groupName);
1279 return g->value(paramName);
1282 int PVParams::valueInt(
const char *groupName,
const char *paramName) {
1283 double v = value(groupName, paramName);
1284 return convertParamToInt(v);
1287 int PVParams::valueInt(
1288 const char *groupName,
1289 const char *paramName,
1291 bool warnIfAbsent) {
1292 double v = value(groupName, paramName, (
double)initialValue, warnIfAbsent);
1293 return convertParamToInt(v);
1296 int PVParams::convertParamToInt(
double value) {
1298 if (value >= (
double)INT_MAX) {
1301 else if (value <= (
double)INT_MIN) {
1305 y = (int)nearbyint(value);
1316 const char *groupName,
1317 const char *paramName,
1318 double initialValue,
1319 bool warnIfAbsent) {
1320 if (present(groupName, paramName)) {
1321 return value(groupName, paramName);
1324 if (warnIfAbsent && worldRank == 0) {
1326 "Using default value %f for parameter \"%s\" in group \"%s\"\n",
1331 return initialValue;
1336 void PVParams::writeParam<bool>(
const char *paramName,
bool paramValue) {
1337 if (mPrintParamsStream !=
nullptr) {
1338 pvAssert(mPrintLuaStream);
1339 std::stringstream vstr(
"");
1340 vstr << (paramValue ?
"true" :
"false");
1341 mPrintParamsStream->printf(
" %-35s = %s;\n", paramName, vstr.str().c_str());
1342 mPrintLuaStream->printf(
" %-35s = %s;\n", paramName, vstr.str().c_str());
1346 bool PVParams::arrayPresent(
const char *groupName,
const char *paramName) {
1349 if (worldRank == 0) {
1350 ErrorLog().printf(
"PVParams::present: couldn't find a group for %s\n", groupName);
1355 return g->arrayPresent(paramName);
1365 PVParams::arrayValues(
const char *groupName,
const char *paramName,
int *size,
bool warnIfAbsent) {
1368 if (worldRank == 0) {
1369 ErrorLog().printf(
"PVParams::value: couldn't find a group for %s\n", groupName);
1373 const float *retval = g->arrayValues(paramName, size);
1374 if (retval == NULL) {
1376 if (worldRank == 0) {
1378 "Using empty array for parameter \"%s\" in group \"%s\"\n", paramName, groupName);
1389 const double *PVParams::arrayValuesDbl(
1390 const char *groupName,
1391 const char *paramName,
1393 bool warnIfAbsent) {
1396 if (worldRank == 0) {
1397 ErrorLog().printf(
"PVParams::value: couldn't find a group for %s\n", groupName);
1401 const double *retval = g->arrayValuesDbl(paramName, size);
1402 if (retval == NULL) {
1404 if (worldRank == 0) {
1406 "Using empty array for parameter \"%s\" in group \"%s\"\n", paramName, groupName);
1412 void PVParams::ioParamString(
1413 enum ParamsIOFlag ioFlag,
1414 const char *groupName,
1415 const char *paramName,
1416 char **paramStringValue,
1417 const char *defaultValue,
1418 bool warnIfAbsent) {
1419 const char *paramString =
nullptr;
1421 case PARAMS_IO_READ:
1422 if (stringPresent(groupName, paramName)) {
1423 paramString = stringValue(groupName, paramName, warnIfAbsent);
1428 if (worldRank == 0 and warnIfAbsent ==
true) {
1429 if (defaultValue !=
nullptr) {
1431 "Using default value \"%s\" for string parameter \"%s\" in group \"%s\"\n",
1438 "Using default value of nullptr for string parameter \"%s\" in group " 1444 paramString = defaultValue;
1446 if (paramString !=
nullptr) {
1447 *paramStringValue = strdup(paramString);
1449 *paramStringValue ==
nullptr,
1450 "Global rank %d process unable to copy param %s in group \"%s\": %s\n",
1457 *paramStringValue =
nullptr;
1460 case PARAMS_IO_WRITE: writeParamString(paramName, *paramStringValue);
1464 void PVParams::ioParamStringRequired(
1465 enum ParamsIOFlag ioFlag,
1466 const char *groupName,
1467 const char *paramName,
1468 char **paramStringValue) {
1469 const char *paramString =
nullptr;
1471 case PARAMS_IO_READ:
1472 paramString = stringValue(groupName, paramName,
false );
1473 if (paramString !=
nullptr) {
1474 *paramStringValue = strdup(paramString);
1476 *paramStringValue ==
nullptr,
1477 "Global Rank %d process unable to copy param %s in group \"%s\": %s\n",
1483 else if (!stringPresent(groupName, paramName)) {
1486 if (worldRank == 0) {
1488 "%s \"%s\": string parameter \"%s\" is required.\n",
1489 groupKeywordFromName(groupName),
1493 MPI_Barrier(icComm->globalCommunicator());
1497 *paramStringValue =
nullptr;
1500 case PARAMS_IO_WRITE: writeParamString(paramName, *paramStringValue);
1508 int PVParams::stringPresent(
const char *groupName,
const char *paramStringName) {
1511 if (worldRank == 0) {
1512 ErrorLog().printf(
"PVParams::stringPresent: couldn't find a group for %s\n", groupName);
1517 return g->stringPresent(paramStringName);
1525 PVParams::stringValue(
const char *groupName,
const char *paramStringName,
bool warnIfAbsent) {
1526 if (stringPresent(groupName, paramStringName)) {
1528 return g->stringValue(paramStringName);
1531 if (warnIfAbsent && worldRank == 0) {
1533 "No parameter string named \"%s\" in group \"%s\"\n", paramStringName, groupName);
1539 void PVParams::writeParamString(
const char *paramName,
const char *svalue) {
1540 if (mPrintParamsStream !=
nullptr) {
1541 pvAssert(mPrintLuaStream);
1542 if (svalue !=
nullptr) {
1543 mPrintParamsStream->printf(
" %-35s = \"%s\";\n", paramName, svalue);
1544 mPrintLuaStream->printf(
" %-35s = \"%s\";\n", paramName, svalue);
1547 mPrintParamsStream->printf(
" %-35s = NULL;\n", paramName);
1548 mPrintLuaStream->printf(
" %-35s = NULL;\n", paramName);
1557 for (
int i = 0; i < numGroups; i++) {
1558 if (strcmp(groupName, groups[i]->name()) == 0) {
1565 const char *PVParams::groupNameFromIndex(
int index) {
1566 bool inbounds = index >= 0 && index < numGroups;
1567 return inbounds ? groups[index]->name() : NULL;
1570 const char *PVParams::groupKeywordFromIndex(
int index) {
1571 bool inbounds = index >= 0 && index < numGroups;
1572 return inbounds ? groups[index]->getGroupKeyword() : NULL;
1575 const char *PVParams::groupKeywordFromName(
const char *name) {
1576 const char *kw = NULL;
1579 kw = g->getGroupKeyword();
1588 void PVParams::addGroup(
char *keyword,
char *name) {
1589 assert((
size_t)numGroups <= groupArraySize);
1592 for (
int k = 0; k < numGroups; k++) {
1593 if (!strcmp(name, groups[k]->name())) {
1594 Fatal().printf(
"Rank %d process: group name \"%s\" duplicated\n", worldRank, name);
1598 if ((
size_t)numGroups == groupArraySize) {
1599 groupArraySize += RESIZE_ARRAY_INCR;
1603 for (
int k = 0; k < numGroups; k++) {
1604 newGroups[k] = groups[k];
1610 groups[numGroups] =
new ParameterGroup(name, stack, arrayStack, stringStack, worldRank);
1611 groups[numGroups]->setGroupKeyword(keyword);
1621 void PVParams::addActiveParamSweep(
const char *group_name,
const char *param_name) {
1623 for (
int p = 0; p < numParamSweeps; p++) {
1624 if (strcmp(paramSweeps[p]->getGroupName(), group_name) == 0
1625 && strcmp(paramSweeps[p]->getParamName(), param_name) == 0) {
1627 "PVParams::addActiveParamSweep: Parameter sweep %s, %s already exists\n",
1633 activeParamSweep->setGroupAndParameter(group_name, param_name);
1636 if (newParamSweeps == NULL) {
1638 "PVParams::action_parameter_sweep: unable to allocate memory for larger paramSweeps\n");
1640 for (
int k = 0; k < numParamSweeps; k++) {
1641 newParamSweeps[k] = paramSweeps[k];
1644 paramSweeps = newParamSweeps;
1645 paramSweeps[numParamSweeps] = activeParamSweep;
1647 newActiveParamSweep();
1650 int PVParams::warnUnread() {
1651 int status = PV_SUCCESS;
1652 for (
int i = 0; i < numberOfGroups(); i++) {
1653 if (groups[i]->warnUnread() != PV_SUCCESS) {
1654 status = PV_FAILURE;
1660 bool PVParams::hasBeenRead(
const char *group_name,
const char *param_name) {
1666 return g->hasBeenRead(param_name);
1669 bool PVParams::presentAndNotBeenRead(
const char *group_name,
const char *param_name) {
1670 bool is_present = present(group_name, param_name);
1672 is_present = arrayPresent(group_name, param_name);
1674 is_present = stringPresent(group_name, param_name);
1675 bool has_been_read = hasBeenRead(group_name, param_name);
1676 return is_present && !has_been_read;
1679 int PVParams::clearHasBeenReadFlags() {
1680 int status = PV_SUCCESS;
1681 for (
int i = 0; i < numberOfGroups(); i++) {
1682 if (groups[i]->clearHasBeenReadFlags() != PV_SUCCESS) {
1683 status = PV_FAILURE;
1689 void PVParams::handleUnnecessaryParameter(
const char *group_name,
const char *param_name) {
1690 if (present(group_name, param_name)) {
1691 if (worldRank == 0) {
1692 const char *class_name = groupKeywordFromName(group_name);
1694 "%s \"%s\" does not use parameter %s, but it is present in the parameters file.\n",
1705 int status = PV_SUCCESS;
1706 const char *class_name = groupKeywordFromName(group_name);
1707 if (stringPresent(group_name, param_name)) {
1708 if (worldRank == 0) {
1710 "%s \"%s\" does not use string parameter %s, but it is present in the parameters " 1716 const char *params_value = stringValue(group_name, param_name,
false );
1722 const char *group_name,
1723 const char *param_name,
1724 const char *correct_value,
1725 bool case_insensitive_flag) {
1726 int status = PV_SUCCESS;
1727 const char *class_name = groupKeywordFromName(group_name);
1728 if (stringPresent(group_name, param_name)) {
1729 if (worldRank == 0) {
1731 "%s \"%s\" does not use string parameter %s, but it is present in the parameters " 1737 const char *params_value = stringValue(group_name, param_name,
false );
1741 if (params_value !=
nullptr && correct_value !=
nullptr) {
1742 char *correct_value_i =
1743 strdup(correct_value);
1744 char *params_value_i =
1745 strdup(params_value);
1746 if (correct_value_i ==
nullptr) {
1747 status = PV_FAILURE;
1748 if (worldRank == 0) {
1750 "%s \"%s\": Rank %d process unable to copy correct string value: %s.\n",
1757 if (params_value_i ==
nullptr) {
1758 status = PV_FAILURE;
1759 if (worldRank == 0) {
1761 "%s \"%s\": Rank %d process unable to copy parameter string value: %s.\n",
1768 if (case_insensitive_flag) {
1769 for (
char *c = params_value_i; *c !=
'\0'; c++) {
1770 *c = (char)tolower((
int)*c);
1772 for (
char *c = correct_value_i; *c !=
'\0'; c++) {
1773 *c = (char)tolower((
int)*c);
1776 if (strcmp(params_value_i, correct_value_i) != 0) {
1777 status = PV_FAILURE;
1778 if (worldRank == 0) {
1780 "%s \"%s\": parameter string %s = \"%s\" is inconsistent with correct value " 1781 "\"%s\". Exiting.\n",
1789 free(correct_value_i);
1790 free(params_value_i);
1792 else if (params_value ==
nullptr && correct_value !=
nullptr) {
1793 status = PV_FAILURE;
1794 if (worldRank == 0) {
1796 "%s \"%s\": parameter string %s = NULL is inconsistent with correct value " 1797 "\"%s\". Exiting.\n",
1804 else if (params_value !=
nullptr && correct_value ==
nullptr) {
1805 status = PV_FAILURE;
1806 if (worldRank == 0) {
1808 "%s \"%s\": parameter string %s = \"%s\" is inconsistent with correct value of " 1817 pvAssert(params_value ==
nullptr && correct_value ==
nullptr);
1818 pvAssert(status == PV_SUCCESS);
1821 if (status != PV_SUCCESS) {
1822 MPI_Barrier(icComm->globalCommunicator());
1832 if (!strcmp(
id,
"debugParsing")) {
1833 debugParsing = (val != 0);
1834 if (worldRank == 0) {
1835 InfoLog(directiveMessage);
1836 directiveMessage.printf(
"debugParsing turned ");
1838 directiveMessage.printf(
"on.\n");
1841 directiveMessage.printf(
"off.\n");
1845 else if (!strcmp(
id,
"disable")) {
1846 disable = (val != 0);
1847 if (worldRank == 0) {
1848 InfoLog(directiveMessage);
1849 directiveMessage.printf(
"Parsing params file ");
1851 directiveMessage.printf(
"disabled.\n");
1854 directiveMessage.printf(
"enabled.\n");
1859 if (worldRank == 0) {
1860 WarnLog().printf(
"Unrecognized directive %s = %f, skipping.\n",
id, val);
1869 void PVParams::action_parameter_group() {
1872 if (debugParsing && worldRank == 0) {
1874 "action_parameter_group: %s \"%s\" parsed successfully.\n",
1880 addGroup(currGroupKeyword, currGroupName);
1882 void PVParams::action_parameter_group_name(
char *keyword,
char *name) {
1886 int len = strlen(++name);
1887 name[len - 1] =
'\0';
1889 if (debugParsing && worldRank == 0) {
1891 "action_parameter_group_name: %s \"%s\" parsed successfully.\n", keyword, name);
1894 currGroupKeyword = keyword;
1895 currGroupName = name;
1905 if (debugParsing && worldRank == 0) {
1907 InfoLog().printf(
"action_parameter_def: %s = %lf\n",
id, val);
1910 checkDuplicates(
id);
1915 void PVParams::action_parameter_def_overwrite(
char *
id,
double val) {
1918 if (debugParsing && worldRank == 0) {
1920 InfoLog().printf(
"action_parameter_def_overwrite: %s = %lf\n",
id, val);
1924 char *param_name = stripOverwriteTag(
id);
1926 for (
int i = 0; i < stack->size(); i++) {
1928 if (strcmp(param->name(), param_name) == 0) {
1933 for (
int i = 0; i < arrayStack->size(); i++) {
1935 if (strcmp(arrayParam->name(), param_name) == 0) {
1938 "%s is defined as an array parameter. Overwriting array parameters with value " 1939 "parameters not implemented yet.\n",
1945 ErrorLog().printf(
"Overwrite: %s is not an existing parameter to overwrite.\n",
id);
1950 currParam->setValue(val);
1953 void PVParams::action_parameter_array(
char *
id) {
1956 if (debugParsing && worldRank == 0) {
1958 InfoLog().printf(
"action_parameter_array: %s\n",
id);
1961 int status = currentParamArray->setName(
id);
1962 assert(status == PV_SUCCESS);
1963 checkDuplicates(
id);
1964 arrayStack->push(currentParamArray);
1965 currentParamArray =
new ParameterArray(PARAMETERARRAYSTACK_INITIALCOUNT);
1968 void PVParams::action_parameter_array_overwrite(
char *
id) {
1971 if (debugParsing && worldRank == 0) {
1973 InfoLog().printf(
"action_parameter_array_overwrite: %s\n",
id);
1977 char *param_name = stripOverwriteTag(
id);
1979 for (
int i = 0; i < arrayStack->size(); i++) {
1981 if (strcmp(arrayParam->name(), param_name) == 0) {
1982 origArray = arrayParam;
1986 for (
int i = 0; i < stack->size(); i++) {
1988 if (strcmp(param->name(), param_name) == 0) {
1991 "%s is defined as a value parameter. Overwriting value parameters with array " 1992 "parameters not implemented yet.\n",
1998 ErrorLog().printf(
"Overwrite: %s is not an existing parameter to overwrite.\n",
id);
2003 origArray->resetArraySize();
2004 for (
int i = 0; i < currentParamArray->getArraySize(); i++) {
2005 origArray->pushValue(currentParamArray->peek(i));
2007 assert(origArray->getArraySize() == currentParamArray->getArraySize());
2008 delete currentParamArray;
2009 currentParamArray =
new ParameterArray(PARAMETERARRAYSTACK_INITIALCOUNT);
2012 void PVParams::action_parameter_array_value(
double val) {
2015 if (debugParsing && worldRank == 0) {
2017 InfoLog().printf(
"action_parameter_array_value %lf\n", val);
2019 int sz = currentParamArray->getArraySize();
2020 int newsize = currentParamArray->pushValue(val);
2021 assert(newsize == sz + 1);
2024 void PVParams::action_parameter_string_def(
const char *
id,
const char *stringval) {
2027 if (debugParsing && worldRank == 0) {
2029 InfoLog().printf(
"action_parameter_string_def: %s = %s\n",
id, stringval);
2032 checkDuplicates(
id);
2033 char *param_value = stripQuotationMarks(stringval);
2034 assert(!stringval || param_value);
2037 stringStack->push(pstr);
2041 void PVParams::action_parameter_string_def_overwrite(
const char *
id,
const char *stringval) {
2044 if (debugParsing && worldRank == 0) {
2046 InfoLog().printf(
"action_parameter_string_def_overwrite: %s = %s\n",
id, stringval);
2050 char *param_name = stripOverwriteTag(
id);
2052 for (
int i = 0; i < stringStack->size(); i++) {
2055 if (strcmp(param->getName(), param_name) == 0) {
2061 ErrorLog().printf(
"Overwrite: %s is not an existing parameter to overwrite.\n",
id);
2063 char *param_value = stripQuotationMarks(stringval);
2064 assert(!stringval || param_value);
2067 currParam->setValue(param_value);
2071 void PVParams::action_parameter_filename_def(
const char *
id,
const char *stringval) {
2074 if (debugParsing && worldRank == 0) {
2076 InfoLog().printf(
"action_parameter_filename_def: %s = %s\n",
id, stringval);
2079 checkDuplicates(
id);
2080 char *param_value = stripQuotationMarks(stringval);
2081 assert(param_value);
2084 stringStack->push(pstr);
2087 void PVParams::action_parameter_filename_def_overwrite(
const char *
id,
const char *stringval) {
2090 if (debugParsing && worldRank == 0) {
2092 InfoLog().printf(
"action_parameter_filename_def_overwrite: %s = %s\n",
id, stringval);
2096 char *param_name = stripOverwriteTag(
id);
2098 for (
int i = 0; i < stringStack->size(); i++) {
2101 if (strcmp(param->getName(), param_name) == 0) {
2108 ErrorLog().printf(
"Overwrite: %s is not an existing parameter to overwrite.\n",
id);
2110 char *param_value = stripQuotationMarks(stringval);
2111 assert(param_value);
2112 currParam->setValue(param_value);
2116 void PVParams::action_include_directive(
const char *stringval) {
2119 if (debugParsing && worldRank == 0) {
2121 InfoLog().printf(
"action_include_directive: including %s\n", stringval);
2125 if (stack->size() != 0 || arrayStack->size() != 0 || stringStack->size() != 0) {
2127 "Import of %s must be the first parameter specified in the group.\n", stringval);
2131 char *param_value = stripQuotationMarks(stringval);
2134 for (
int groupidx = 0; groupidx < numGroups; groupidx++) {
2136 if (strcmp(groups[groupidx]->name(), param_value) == 0) {
2137 includeGroup = groups[groupidx];
2141 if (!includeGroup) {
2142 ErrorLog().printf(
"Include: include group %s is not defined.\n", param_value);
2145 if (strcmp(includeGroup->getGroupKeyword(), currGroupKeyword) != 0) {
2147 "Include: Cannot include group %s, which is a %s, into a %s. Group types must be the " 2150 includeGroup->getGroupKeyword(),
2156 assert(stack->size() == 0);
2160 assert(arrayStack->size() == 0);
2164 assert(stringStack->size() == 0);
2169 void PVParams::action_parameter_sweep_open(
const char *groupname,
const char *paramname) {
2173 currSweepGroupName = stripQuotationMarks(groupname);
2174 assert(currSweepGroupName);
2175 currSweepParamName = strdup(paramname);
2176 if (debugParsing && worldRank == 0) {
2179 "action_parameter_sweep_open: Sweep for group %s, parameter \"%s\" starting\n",
2186 void PVParams::action_parameter_sweep_close() {
2189 addActiveParamSweep(currSweepGroupName, currSweepParamName);
2190 if (debugParsing && worldRank == 0) {
2192 "action_parameter_group: ParameterSweep for %s \"%s\" parsed successfully.\n",
2194 currSweepParamName);
2198 free(currSweepGroupName);
2199 free(currSweepParamName);
2202 void PVParams::action_parameter_sweep_values_number(
double val) {
2205 if (debugParsing && worldRank == 0) {
2207 InfoLog().printf(
"action_parameter_sweep_values_number: %f\n", val);
2210 activeParamSweep->pushNumericValue(val);
2213 void PVParams::action_parameter_sweep_values_string(
const char *stringval) {
2216 if (debugParsing && worldRank == 0) {
2218 InfoLog().printf(
"action_sweep_values_string: %s\n", stringval);
2221 char *
string = stripQuotationMarks(stringval);
2222 assert(!stringval ||
string);
2224 activeParamSweep->pushStringValue(
string);
2228 void PVParams::action_parameter_sweep_values_filename(
const char *stringval) {
2231 if (debugParsing && worldRank == 0) {
2233 InfoLog().printf(
"action_sweep_values_filename: %s\n", stringval);
2236 char *filename = stripQuotationMarks(stringval);
2238 activeParamSweep->pushStringValue(filename);
2242 void PVParams::checkDuplicates(
const char *paramName) {
2243 bool hasDuplicate =
false;
2244 for (
int k = 0; k < stack->size(); k++) {
2246 if (!strcmp(paramName, parm->name())) {
2248 "Rank %d process: The params group for %s \"%s\" duplicates " 2249 "parameter \"%s\".\n",
2254 hasDuplicate =
true;
2257 for (
int k = 0; k < arrayStack->size(); k++) {
2258 if (!strcmp(paramName, arrayStack->peek(k)->name())) {
2260 "Rank %d process: The params group for %s \"%s\" duplicates " 2261 "array parameter \"%s\".\n",
2266 hasDuplicate =
true;
2269 for (
int k = 0; k < stringStack->size(); k++) {
2270 if (!strcmp(paramName, stringStack->peek(k)->getName())) {
2272 "Rank %d process: The params group for %s \"%s\" duplicates " 2273 "string parameter \"%s\".\n",
2278 hasDuplicate =
true;
2286 char *PVParams::stripQuotationMarks(
const char *s) {
2296 char *noquotes = NULL;
2297 int len = strlen(s);
2298 if (len >= 2 && s[0] ==
'"' && s[len - 1] ==
'"') {
2299 noquotes = (
char *)calloc(len - 1,
sizeof(
char));
2300 memcpy(noquotes, s + 1, len - 2);
2301 noquotes[len - 2] =
'\0';
2306 char *PVParams::stripOverwriteTag(
const char *s) {
2308 int len = strlen(s);
2310 if (len >= 1 && s[0] ==
'@') {
2311 notag = (
char *)calloc(len,
sizeof(
char));
2312 memcpy(notag, s + 1, len - 1);
2313 notag[len - 1] =
'\0';
ParameterStringStack * copyStringStack()
ParameterArrayStack * copyArrayStack()
int push(Parameter *param)
int present(const char *groupName, const char *paramName)
ParameterGroup * group(const char *groupName)
double value(const char *groupName, const char *paramName)
ParameterStack(int maxCount)
void action_parameter_def(char *id, double val)
void action_pvparams_directive(char *id, double val)
void handleUnnecessaryStringParameter(const char *group_name, const char *param_name)
ParameterStack * copyStack()