Skip to content

Commit

Permalink
PR-665 Add tests for glue generator as preliminary for for adding sup…
Browse files Browse the repository at this point in the history
…port for DNP3
  • Loading branch information
Garret Fick committed Apr 10, 2019
1 parent e6206dd commit 9185e95
Show file tree
Hide file tree
Showing 5 changed files with 15,237 additions and 68 deletions.
11 changes: 9 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,12 @@ public/

*.pyc

# IDE files for Visual Studio Code
*.vscode/
# IDE files for Visual Studio Code and Visual Studio
CMakeSettings.json
*.vscode/
*.vs/

# Build directories
webserver/bin
webserver/build
obj/
27 changes: 27 additions & 0 deletions utils/glue_generator_src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.0.0)

# CMake build for OpenPLC glue generator. The glue generator takes
# generated C code from the MATIEC compiler and then generates necessary
# glue to bind the MATIEC code with the OpenPLC runtime.
project(openplc_gluegenerator)

option(WERROR "Set all warnings to errors" ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

# Optional build capabilities
option(OPLCGLUE_ALL "Build all optional projects (tests)" ON)
option(OPLCGLUE_TEST "Build tests" OFF)

if(OPLCGLUE_ALL)
message("enabling all optional components")
set(OPLCGLUE_TEST ON)
endif()

# The main application that we always build
add_executable(glue_generator glue_generator.cpp)

#if(OPLCGLUE_TEST)
add_executable(glue_generator_test ./test/glue_generator_test.cpp)
#endif()
156 changes: 90 additions & 66 deletions utils/glue_generator_src/glue_generator.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
#include <iostream>
#include <fstream>
#include <string>

#include <string.h>
#include <stdlib.h>
#include <cstring>
#include <cstdlib>

using namespace std;

ifstream locatedVars;
ofstream glueVars;

void generateHeader()
/// Write the header to the output stream. The header is common among all glueVars files.
/// @param glueVars The output stream to write to.
void generateHeader(ostream& glueVars)
{
if (glueVars.is_open())
{
glueVars << "\
glueVars << "\
//-----------------------------------------------------------------------------\r\n\
// Copyright 2015 Thiago Alves\r\n\
// This file is part of the OpenPLC Software Stack.\r\n\
Expand Down Expand Up @@ -78,58 +74,41 @@ IEC_LINT *special_functions[BUFFER_SIZE];\r\n\
\r\n\
void glueVars()\r\n\
{\r\n";

}

else
{
cout << "Error opening glueVars.cpp file!" << endl;
}
}

int parseIecVars(char *varName, char *varType)
int parseIecVars(istream& locatedVars, char *varName, char *varType)
{
string line;
char buffer[1024];

if (locatedVars.is_open())
{
if (getline(locatedVars, line))
{
int i = 0, j = 0;
strncpy(buffer, line.c_str(), 1024);
for (i = 0; buffer[i] != '('; i++);
i++;

while (buffer[i] != ',')
{
varType[j] = buffer[i];
i++; j++;
varType[j] = '\0';
}
i++; j=0;

while (buffer[i] != ',')
{
varName[j] = buffer[i];
i++; j++;
varName[j] = '\0';
}
if (getline(locatedVars, line))
{
int i = 0, j = 0;
strncpy(buffer, line.c_str(), 1024);
for (i = 0; buffer[i] != '('; i++);
i++;

return 1;
}
while (buffer[i] != ',')
{
varType[j] = buffer[i];
i++; j++;
varType[j] = '\0';
}
i++; j=0;

else
{
return 0;
}
}
while (buffer[i] != ',')
{
varName[j] = buffer[i];
i++; j++;
varName[j] = '\0';
}

else
{
cout << "Error opening located variables file!" << endl;
return 0;
}
return 1;
}
else
{
return 0;
}
}

void findPositions(char *varName, int *pos1, int *pos2)
Expand Down Expand Up @@ -162,7 +141,7 @@ void findPositions(char *varName, int *pos1, int *pos2)
*pos2 = atoi(tempBuffer);
}

void glueVar(char *varName, char *varType)
void glueVar(ostream& glueVars, char *varName, char *varType)
{
cout << "varName: " << varName << "\tvarType: " << varType << endl;
int pos1, pos2;
Expand Down Expand Up @@ -198,7 +177,7 @@ void glueVar(char *varName, char *varType)
case 'X':
glueVars << "\tbool_output[" << pos1 << "][" << pos2 << "] = " << varName << ";\r\n";
break;
case 'B':
case 'B':
glueVars << "\tbyte_output[" << pos1 << "] = " << varName << ";\r\n";
break;
case 'W':
Expand Down Expand Up @@ -227,7 +206,7 @@ void glueVar(char *varName, char *varType)
}
}

void generateBottom()
void generateBottom(ostream& glueVars)
{
glueVars << "}\r\n\
\r\n\
Expand All @@ -243,21 +222,66 @@ void updateTime()\r\n\
}";
}

int main()
void generateBody(istream& locatedVars, ostream& glueVars) {
// Start the generation process.
char iecVar_name[100];
char iecVar_type[100];

while (parseIecVars(locatedVars, iecVar_name, iecVar_type))
{
glueVar(glueVars, iecVar_name, iecVar_type);
}
}

/// This is our main function. We define it with a different name and then
/// call it from the main function so that we can mock it for the purpose
/// of testing.
int mainImpl(int argc, char *argv[])
{
char iecVar_name[100];
char iecVar_type[100];
locatedVars.open("LOCATED_VARIABLES.h", ios::in);
glueVars.open("glueVars.cpp", ios::trunc);
// Parse the command line arguments - if they exist. Show the help if there are too many arguments
// or if the first argument is for help.
bool show_help = argc >= 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0);
if (show_help || (argc != 1 && argc != 3)) {
cout << "Usage " << endl << endl;
cout << " glue_generator [options] <path-to-located-variables.h> <path-to-glue-vars.cpp>" << endl << endl;
cout << "Reads the LOCATED_VARIABLES.h file generated by the MATIEC compiler and produces" << endl;
cout << "glueVars.cpp for the OpenPLC runtime. If not specified, paths are relative to" << endl;
cout << "the current directory." << endl << endl;
cout << "Options" << endl;
cout << " --help,-h = Print usage information and exit." << endl;
return 0;
}

generateHeader();
// If we have 3 arguments, then the user provided input and output paths
string input_file_name("LOCATED_VARIABLES.h");
string output_file_name("glueVars.cpp");
if (argc == 3) {
input_file_name = argv[1];
output_file_name = argv[2];
}

while (parseIecVars(iecVar_name, iecVar_type))
{
glueVar(iecVar_name, iecVar_type);
// Try to open the files for reading and writing.
ifstream locatedVars(input_file_name, ios::in);
if (!locatedVars.is_open()) {
cout << "Error opening located variables file at " << input_file_name << endl;
return 1;
}
ofstream glueVars(output_file_name, ios::trunc);
if (!glueVars.is_open()) {
cout << "Error opening glue variables file at " << output_file_name << endl;
return 2;
}

generateBottom();
generateHeader(glueVars);
generateBody(locatedVars, glueVars);
generateBottom(glueVars);

return 0;
}

// For testing, we need to allow omitting the main function defined here.
#ifndef OPLCGLUE_OMIT_MAIN
int main(int argc, char *argv[]) {
return mainImpl(argc, argv);
}
#endif // OPLCGLUE_OMIT_MAIN
Loading

0 comments on commit 9185e95

Please sign in to comment.