/*! * @function pgm_load * Loads the pgm image at [filename] into a [width] x [height] unsigned char matrix, * and stores the pointer into [img]. * @param img * A pointer to an unsigned char pointer where the image will be stored. * @param height * A pointer to an int where the n of rows of the image will be stored. * @param width * A pointer to an int where the n of cols of the image will be stored. * @param filename * The name of the file to be read. * @return * 0 on success, non-0 on failure. */ int pgm_load(unsigned char ** const img, int * const height, int * const width, const char * const filename) { const char * const fname = "pgm_load"; if (NULL == img) { Debug_out(DEBUG_PGM, "%s: NULL pointer argument.\n", fname); goto error1; } char **lines = parseLines(filename); int i = 0, j; int l_width, l_height; unsigned int tmp; /* parse all file lines */ if (NULL == lines) { Debug_out(DEBUG_PGM, "%s: unable to read file '%s'.\n", fname, filename); goto error1; } /* check that first line says P2 */ if (NULL == lines[i]) { Debug_out(DEBUG_PGM, "%s: image ended too early.\n", fname); goto error2; } if (!StringUtils_startsWith(lines[i], "P2")) { Debug_out(DEBUG_PGM, "%s: illegal image start: %s.\n", fname, lines[i]); goto error2; } ++i; /* skip all comment lines */ while ((NULL != lines[i]) && (StringUtils_startsWith(lines[i], "#"))) { /* Comment line */ Debug_out(DEBUG_PGM, "%s: %s.\n", fname, lines[i]); ++i; } if (NULL == lines[i]) { Debug_out(DEBUG_PGM, "%s: image ended too early.\n", fname); goto error2; } /* parse width and height */ if (2 != sscanf(lines[i], "%d %d", &l_width, &l_height)) { Debug_out(DEBUG_PGM, "%s: error scanning line %d: %s.\n", fname, i, lines[i]); goto error2; } Debug_out(DEBUG_PGM, "%s: image size is %d x %d.\n", fname, l_width, l_height); ++i; if (NULL == lines[i]) { Debug_out(DEBUG_PGM, "%s: image ended too early.\n", fname); goto error2; } /* skip image max value */ Debug_out(DEBUG_PGM, "%s: image max value is %s.\n", fname, lines[i]); ++i; if (NULL == lines[i]) { Debug_out(DEBUG_PGM, "%s: image ended too early.\n", fname); goto error2; } /* allocate image and parse it */ *img = calloc(l_width * l_height, sizeof(unsigned char)); if (NULL == img) { Debug_out(DEBUG_PGM, "%s: calloc failed.\n", fname); goto error2; } Debug_out(DEBUG_PGM, "%s: Result image buffer allocated.\n", fname); for (j = 0; j < l_width * l_height; ++j) { if (NULL == lines[i+j]) { Debug_out(DEBUG_PGM, "%s: image ended too early.\n", fname); goto error3; } else if (1 != sscanf(lines[i+j], "%u", &tmp)) { Debug_out(DEBUG_PGM, "%s: error scanning line %d: %s.\n", fname, i+j, lines[i+j]); goto error3; } Debug_out(DEBUG_PGM, "%s: Pixel %d is %d.\n", fname, j, tmp); (*img)[j] = tmp; } /* save width and height, and free parsed lines */ if (NULL != width) { *width = l_width; } if (NULL != height) { *height = l_height; } Vector_free((void **) lines); return 0; error3: free(img); error2: Vector_free((void **) lines); error1: return 1; }
IedModel* ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle) { int bytesRead = 1; bool stateInModel = false; int indendation = 0; IedModel* model = NULL; LogicalDevice* currentLD = NULL; LogicalNode* currentLN = NULL; ModelNode* currentModelNode = NULL; DataSet* currentDataSet = NULL; GSEControlBlock* currentGoCB = NULL; char nameString[130]; char nameString2[130]; char nameString3[130]; int currentLine = 0; while (bytesRead > 0) { bytesRead = readLine(fileHandle, lineBuffer, READ_BUFFER_MAX_SIZE); currentLine++; if (bytesRead > 0) { lineBuffer[bytesRead] = 0; if (stateInModel) { if (StringUtils_startsWith((char*) lineBuffer, "}")) { if (indendation == 1) { stateInModel = false; indendation = 0; } else if (indendation == 2) { indendation = 1; } else if (indendation == 3) { indendation = 2; } else if (indendation == 4) { indendation = 3; } else if (indendation > 4) { currentModelNode = currentModelNode->parent; indendation--; } } else if (indendation == 1) { if (StringUtils_startsWith((char*) lineBuffer, "LD")) { indendation = 2; if (sscanf((char*) lineBuffer, "LD(%s)", nameString) < 1) goto exit_error; terminateString(nameString, ')'); currentLD = LogicalDevice_create(nameString, model); } else goto exit_error; } else if (indendation == 2) { if (StringUtils_startsWith((char*) lineBuffer, "LN")) { indendation = 3; if (sscanf((char*) lineBuffer, "LN(%s)", nameString) < 1) goto exit_error; terminateString(nameString, ')'); currentLN = LogicalNode_create(nameString, currentLD); } else goto exit_error; } else if (indendation == 3) { if (StringUtils_startsWith((char*) lineBuffer, "DO")) { indendation = 4; int arrayElements = 0; sscanf((char*) lineBuffer, "DO(%s %i)", nameString, &arrayElements); currentModelNode = (ModelNode*) DataObject_create(nameString, (ModelNode*) currentLN, arrayElements); } else if (StringUtils_startsWith((char*) lineBuffer, "DS")) { indendation = 4; sscanf((char*) lineBuffer, "DS(%s)", nameString); terminateString(nameString, ')'); currentDataSet = DataSet_create(nameString, currentLN); } else if (StringUtils_startsWith((char*) lineBuffer, "RC")) { int isBuffered; uint32_t confRef; int trgOps; int options; uint32_t bufTm; uint32_t intgPd; int matchedItems = sscanf((char*) lineBuffer, "RC(%s %s %i %s %u %i %i %u %u)", nameString, nameString2, &isBuffered, nameString3, &confRef, &trgOps, &options, &bufTm, &intgPd); if (matchedItems < 9) goto exit_error; char* rptId = NULL; if (strcmp(nameString2, "-") != 0) rptId = nameString2; char* dataSetName = NULL; if (strcmp(nameString3, "-") != 0) dataSetName = nameString3; ReportControlBlock_create(nameString, currentLN, rptId, (bool) isBuffered, dataSetName, confRef, trgOps, options, bufTm, intgPd); } else if (StringUtils_startsWith((char*) lineBuffer, "LC")) { uint32_t trgOps; uint32_t intgPd; int logEna; int withReasonCode; int matchedItems = sscanf((char*) lineBuffer, "LC(%s %s %s %u %u %i %i)", nameString, nameString2, nameString3, &trgOps, &intgPd, &logEna, &withReasonCode); if (matchedItems < 7) goto exit_error; char* dataSet = NULL; if (strcmp(nameString2, "-") != 0) dataSet = nameString2; char* logRef = NULL; if (strcmp(nameString3, "-") != 0) logRef = nameString3; LogControlBlock_create(nameString, currentLN, dataSet, logRef, trgOps, intgPd, logEna, withReasonCode); } else if (StringUtils_startsWith((char*) lineBuffer, "LOG")) { int matchedItems = sscanf((char*) lineBuffer, "LOG(%s)", nameString); if (matchedItems < 1) goto exit_error; /* remove trailing ')' character */ int nameLen = strlen(nameString); nameString[nameLen - 1] = 0; Log_create(nameString, currentLN); } else if (StringUtils_startsWith((char*) lineBuffer, "GC")) { uint32_t confRef; int fixedOffs; int minTime = -1; int maxTime = -1; int matchedItems = sscanf((char*) lineBuffer, "GC(%s %s %s %u %i %i %i)", nameString, nameString2, nameString3, &confRef, &fixedOffs, &minTime, &maxTime); if (matchedItems < 5) goto exit_error; currentGoCB = GSEControlBlock_create(nameString, currentLN, nameString2, nameString3, confRef, fixedOffs, minTime, maxTime); indendation = 4; } #if (CONFIG_IEC61850_SETTING_GROUPS == 1) else if (StringUtils_startsWith((char*) lineBuffer, "SG")) { if (strcmp(currentLN->name, "LLN0") != 0) { if (DEBUG_IED_SERVER) printf("Setting group control is not defined in LLN0\n"); goto exit_error; } int actSG; int numOfSGs; int matchedItems = sscanf((char*) lineBuffer, "SG(%i %i)", &actSG, &numOfSGs); if (matchedItems < 2) goto exit_error; SettingGroupControlBlock_create(currentLN, actSG, numOfSGs); } #endif /* (CONFIG_IEC61850_SETTING_GROUPS == 1) */ else { if (DEBUG_IED_SERVER) printf("IED_SERVER: Unknown identifier (%s)\n", lineBuffer); goto exit_error; } } else if (indendation > 3) { if (StringUtils_startsWith((char*) lineBuffer, "DO")) { indendation++; int arrayElements = 0; int matchedItems = sscanf((char*) lineBuffer, "DO(%s %i)", nameString, &arrayElements); if (matchedItems != 2) goto exit_error; currentModelNode = (ModelNode*) DataObject_create(nameString, currentModelNode, arrayElements); } else if (StringUtils_startsWith((char*) lineBuffer, "DA")) { int arrayElements = 0; int attributeType = 0; int functionalConstraint = 0; int triggerOptions = 0; uint32_t sAddr = 0; sscanf((char*) lineBuffer, "DA(%s %i %i %i %i %u)", nameString, &arrayElements, &attributeType, &functionalConstraint, &triggerOptions, &sAddr); DataAttribute* dataAttribute = DataAttribute_create(nameString, currentModelNode, (DataAttributeType) attributeType, (FunctionalConstraint) functionalConstraint, triggerOptions, arrayElements, sAddr); char* valueIndicator = strchr((char*) lineBuffer, '='); if (valueIndicator != NULL) { switch (dataAttribute->type) { case IEC61850_UNICODE_STRING_255: { char* stringStart = valueIndicator + 2; terminateString(stringStart, '"'); dataAttribute->mmsValue = MmsValue_newMmsString(stringStart); } break; case IEC61850_VISIBLE_STRING_255: case IEC61850_VISIBLE_STRING_129: case IEC61850_VISIBLE_STRING_65: case IEC61850_VISIBLE_STRING_64: case IEC61850_VISIBLE_STRING_32: { char* stringStart = valueIndicator + 2; terminateString(stringStart, '"'); dataAttribute->mmsValue = MmsValue_newVisibleString(stringStart); } break; case IEC61850_INT8: case IEC61850_INT16: case IEC61850_INT32: case IEC61850_INT64: case IEC61850_INT128: case IEC61850_ENUMERATED: { int32_t intValue; if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error; dataAttribute->mmsValue = MmsValue_newIntegerFromInt32(intValue); } break; case IEC61850_INT8U: case IEC61850_INT16U: case IEC61850_INT24U: case IEC61850_INT32U: { uint32_t uintValue; if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error; dataAttribute->mmsValue = MmsValue_newUnsignedFromUint32(uintValue); } break; case IEC61850_FLOAT32: { float floatValue; if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error; dataAttribute->mmsValue = MmsValue_newFloat(floatValue); } break; case IEC61850_FLOAT64: { double doubleValue; if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error; dataAttribute->mmsValue = MmsValue_newDouble(doubleValue); } break; case IEC61850_BOOLEAN: { int boolean; if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error; dataAttribute->mmsValue = MmsValue_newBoolean((bool) boolean); } break; default: break; } } int lineLength = strlen((char*) lineBuffer); if (lineBuffer[lineLength - 1] == '{') { indendation++; currentModelNode = (ModelNode*) dataAttribute; } } else if (StringUtils_startsWith((char*) lineBuffer, "DE")) { sscanf((char*) lineBuffer, "DE(%s)", nameString); terminateString(nameString, ')'); DataSetEntry_create(currentDataSet, nameString, -1, NULL); } else if (StringUtils_startsWith((char*) lineBuffer, "PA")) { uint32_t vlanPrio; uint32_t vlanId; uint32_t appId; int matchedItems = sscanf((char*) lineBuffer, "PA(%u %u %u %s)", &vlanPrio, &vlanId, &appId, nameString); if ((matchedItems != 4) || (currentGoCB == NULL)) goto exit_error; terminateString(nameString, ')'); if (strlen(nameString) != 12) goto exit_error; if (StringUtils_createBufferFromHexString(nameString, (uint8_t*) nameString2) != 6) goto exit_error; PhyComAddress* dstAddress = PhyComAddress_create((uint8_t) vlanPrio, (uint16_t) vlanId, (uint16_t) appId, (uint8_t*) nameString2); GSEControlBlock_addPhyComAddress(currentGoCB, dstAddress); } else goto exit_error; } } else { if (StringUtils_startsWith((char*) lineBuffer, "MODEL{")) { model = IedModel_create(""); stateInModel = true; indendation = 1; } else if (StringUtils_startsWith((char*) lineBuffer, "MODEL(")) { sscanf((char*) lineBuffer, "MODEL(%s)", nameString); terminateString(nameString, ')'); model = IedModel_create(nameString); stateInModel = true; indendation = 1; } else goto exit_error; } } } return model; exit_error: if (DEBUG_IED_SERVER) printf("IED_SERVER: error parsing line %i (indendation level = %i)\n", currentLine, indendation); IedModel_destroy(model); return NULL; }