--- a/absyntax_utils/Makefile.in Thu Nov 22 19:19:48 2012 +0000
+++ b/absyntax_utils/Makefile.in Thu Nov 22 19:26:56 2012 +0000
@@ -93,9 +93,7 @@
search_varfb_instance_type.$(OBJEXT) \
search_var_instance_decl.$(OBJEXT) \
spec_init_separator.$(OBJEXT) type_initial_value.$(OBJEXT) \
- debug_ast.$(OBJEXT) \
- get_datatype_info.$(OBJEXT)
-
+ debug_ast.$(OBJEXT) get_datatype_info.$(OBJEXT)
libabsyntax_utils_a_OBJECTS = $(am_libabsyntax_utils_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -236,7 +234,6 @@
debug_ast.cc \
get_datatype_info.cc
-
all: all-am
.SUFFIXES:
--- a/absyntax_utils/add_en_eno_param_decl.hh Thu Nov 22 19:19:48 2012 +0000
+++ b/absyntax_utils/add_en_eno_param_decl.hh Thu Nov 22 19:26:56 2012 +0000
@@ -42,6 +42,9 @@
* and eno_param_declaration_c objects.
*/
+#ifndef _ADD_EN_ENO_PARAM_DECL_HH
+#define _ADD_EN_ENO_PARAM_DECL_HH
+
#include "../absyntax/visitor.hh"
@@ -96,9 +99,11 @@
}; // function_param_iterator_c
+#endif /* _ADD_EN_ENO_PARAM_DECL_HH */
+
--- a/main.cc Thu Nov 22 19:19:48 2012 +0000
+++ b/main.cc Thu Nov 22 19:26:56 2012 +0000
@@ -67,21 +67,28 @@
-//#include <stdio.h> // printf()
+#include <stdio.h>
#include <getopt.h>
#include <string.h>
-#include <stdlib.h> // EXIT_FAILURE
-#include "absyntax/absyntax.hh" // symbol_c type
-
-/* A macro for printing out internal parser errors... */
-#include <iostream> // required for std::cerr
+#include <stdlib.h>
+#include <stdarg.h>
+#include <iostream>
+
+
+#include "config/config.h"
+#include "absyntax/absyntax.hh"
+#include "absyntax_utils/absyntax_utils.hh"
+#include "stage1_2/stage1_2.hh"
+#include "stage3/stage3.hh"
+#include "stage4/stage4.hh"
+#include "main.hh"
+
#ifndef HGVERSION
-#define HGVERSION ""
+ #define HGVERSION ""
#endif
-#include "main.hh" // symbol_c type
-#include <stdarg.h> // required for va_start(), va_list
+
void error_exit(const char *file_name, int line_no, const char *errmsg, ...) {
va_list argptr;
@@ -101,28 +108,20 @@
}
-
-#include "config/config.h"
-#include "stage1_2/stage1_2.hh"
-#include "absyntax_utils/absyntax_utils.hh"
-
-int stage3(symbol_c *tree_root);
-int stage4(symbol_c *tree_root, const char *builddir);
-
-
static void printusage(const char *cmd) {
- printf("syntax: %s [-h] [-v] [-f] [-s] [-I <include_directory>] [-T <target_directory>] <input_file>\n", cmd);
+ printf("\nsyntax: %s [-h] [-v] [-f] [-s] [-c] [-I <include_directory>] [-T <target_directory>] <input_file>\n", cmd);
printf(" h : show this help message\n");
printf(" v : print version number\n");
printf(" f : display full token location on error messages\n");
/******************************************************/
- /* whether we are suporting safe extensions */
+ /* whether we are supporting safe extensions */
/* as defined in PLCopen - Technical Committee 5 */
/* Safety Software Technical Specification, */
/* Part 1: Concepts and Function Blocks, */
- /* Version 1.0 – Official Release */
+ /* Version 1.0 is Official Release */
/******************************************************/
printf(" s : allow use of safe extensions\n");
+ printf(" c : create conversion functions\n");
printf("\n");
printf("%s - Copyright (C) 2003-2011 \n"
"This program comes with ABSOLUTELY NO WARRANTY!\n"
@@ -137,29 +136,34 @@
stage1_2_options_t stage1_2_options = {false, false, NULL};
int optres, errflg = 0;
int path_len;
-/*
- extern char *optarg;
- extern int optind, optopt;
-*/
+
/******************************************/
/* Parse command line options... */
/******************************************/
- while ((optres = getopt(argc, argv, ":hvfsI:T:")) != -1) {
+ while ((optres = getopt(argc, argv, ":hvfscI:T:")) != -1) {
switch(optres) {
case 'h':
printusage(argv[0]);
return 0;
+
case 'v':
fprintf(stdout, "%s version %s\n"
"changeset id: %s\n", PACKAGE_NAME, PACKAGE_VERSION, HGVERSION);
- return 0;
+ return 0;
+
case 'f':
stage1_2_options.full_token_loc = true;
break;
+
case 's':
stage1_2_options.safe_extensions = true;
break;
+
+ case 'c':
+ stage1_2_options.conversion_functions = true;
+ break;
+
case 'I':
/* NOTE: To improve the usability under windows:
* We delete last char's path if it ends with "\".
@@ -170,20 +174,24 @@
if (optarg[path_len] == '\\') optarg[path_len]= '\0';
stage1_2_options.includedir = optarg;
break;
+
case 'T':
/* NOTE: see note above */
path_len = strlen(optarg) - 1;
if (optarg[path_len] == '\\') optarg[path_len]= '\0';
builddir = optarg;
break;
+
case ':': /* -I or -T without operand */
fprintf(stderr, "Option -%c requires an operand\n", optopt);
errflg++;
break;
+
case '?':
fprintf(stderr, "Unrecognized option: -%c\n", optopt);
errflg++;
break;
+
default:
fprintf(stderr, "Unknown error while parsing command line options.");
errflg++;
@@ -202,9 +210,8 @@
}
if (errflg) {
- printf("\n");
- printusage(argv[0]);
- return EXIT_FAILURE;
+ printusage(argv[0]);
+ return EXIT_FAILURE;
}
@@ -225,7 +232,6 @@
if (stage3(tree_root) < 0)
return EXIT_FAILURE;
-
/* 3rd Pass */
if (stage4(tree_root, builddir) < 0)
return EXIT_FAILURE;
--- a/stage1_2/Makefile.am Thu Nov 22 19:19:48 2012 +0000
+++ b/stage1_2/Makefile.am Thu Nov 22 19:26:56 2012 +0000
@@ -16,6 +16,7 @@
libstage1_2_a_SOURCES = \
iec_flex.ll \
iec_bison.yy \
+ create_enumtype_conversion_functions.cc \
stage1_2.cc
libstage1_2_a_CPPFLAGS = -DDEFAULT_LIBDIR='"lib"' -I../../absyntax
--- a/stage1_2/Makefile.in Thu Nov 22 19:19:48 2012 +0000
+++ b/stage1_2/Makefile.in Thu Nov 22 19:26:56 2012 +0000
@@ -78,6 +78,7 @@
libstage1_2_a_LIBADD =
am_libstage1_2_a_OBJECTS = libstage1_2_a-iec_flex.$(OBJEXT) \
libstage1_2_a-iec_bison.$(OBJEXT) \
+ libstage1_2_a-create_enumtype_conversion_functions.$(OBJEXT) \
libstage1_2_a-stage1_2.$(OBJEXT)
libstage1_2_a_OBJECTS = $(am_libstage1_2_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
@@ -214,6 +215,7 @@
libstage1_2_a_SOURCES = \
iec_flex.ll \
iec_bison.yy \
+ create_enumtype_conversion_functions.cc \
stage1_2.cc
libstage1_2_a_CPPFLAGS = -DDEFAULT_LIBDIR='"lib"' -I../../absyntax
@@ -297,6 +299,7 @@
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstage1_2_a-iec_bison.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstage1_2_a-iec_flex.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstage1_2_a-stage1_2.Po@am__quote@
@@ -343,6 +346,20 @@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstage1_2_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libstage1_2_a-iec_bison.obj `if test -f 'iec_bison.cc'; then $(CYGPATH_W) 'iec_bison.cc'; else $(CYGPATH_W) '$(srcdir)/iec_bison.cc'; fi`
+libstage1_2_a-create_enumtype_conversion_functions.o: create_enumtype_conversion_functions.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstage1_2_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libstage1_2_a-create_enumtype_conversion_functions.o -MD -MP -MF $(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Tpo -c -o libstage1_2_a-create_enumtype_conversion_functions.o `test -f 'create_enumtype_conversion_functions.cc' || echo '$(srcdir)/'`create_enumtype_conversion_functions.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Tpo $(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='create_enumtype_conversion_functions.cc' object='libstage1_2_a-create_enumtype_conversion_functions.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstage1_2_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libstage1_2_a-create_enumtype_conversion_functions.o `test -f 'create_enumtype_conversion_functions.cc' || echo '$(srcdir)/'`create_enumtype_conversion_functions.cc
+
+libstage1_2_a-create_enumtype_conversion_functions.obj: create_enumtype_conversion_functions.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstage1_2_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libstage1_2_a-create_enumtype_conversion_functions.obj -MD -MP -MF $(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Tpo -c -o libstage1_2_a-create_enumtype_conversion_functions.obj `if test -f 'create_enumtype_conversion_functions.cc'; then $(CYGPATH_W) 'create_enumtype_conversion_functions.cc'; else $(CYGPATH_W) '$(srcdir)/create_enumtype_conversion_functions.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Tpo $(DEPDIR)/libstage1_2_a-create_enumtype_conversion_functions.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='create_enumtype_conversion_functions.cc' object='libstage1_2_a-create_enumtype_conversion_functions.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstage1_2_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libstage1_2_a-create_enumtype_conversion_functions.obj `if test -f 'create_enumtype_conversion_functions.cc'; then $(CYGPATH_W) 'create_enumtype_conversion_functions.cc'; else $(CYGPATH_W) '$(srcdir)/create_enumtype_conversion_functions.cc'; fi`
+
libstage1_2_a-stage1_2.o: stage1_2.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstage1_2_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libstage1_2_a-stage1_2.o -MD -MP -MF $(DEPDIR)/libstage1_2_a-stage1_2.Tpo -c -o libstage1_2_a-stage1_2.o `test -f 'stage1_2.cc' || echo '$(srcdir)/'`stage1_2.cc
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libstage1_2_a-stage1_2.Tpo $(DEPDIR)/libstage1_2_a-stage1_2.Po
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage1_2/create_enumtype_conversion_functions.cc Thu Nov 22 19:26:56 2012 +0000
@@ -0,0 +1,313 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it)
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+#include <sstream>
+#include "create_enumtype_conversion_functions.hh"
+
+/* set to 1 to see debug info during execution */
+static const int debug = 0;
+
+/*
+ * functionDataType array contains all supported data type conversion.
+ */
+const char *create_enumtype_conversion_functions_c::functionDataType[] = {
+ "STRING",
+ "SINT" ,
+ "INT" ,
+ "DINT" ,
+ "LINT" ,
+ "USINT" ,
+ "UNIT" ,
+ "UDINT" ,
+ "ULINT" ,
+ NULL
+};
+
+create_enumtype_conversion_functions_c::create_enumtype_conversion_functions_c(symbol_c *ignore) {
+
+}
+
+create_enumtype_conversion_functions_c::~create_enumtype_conversion_functions_c(void) {
+
+}
+
+std::string &create_enumtype_conversion_functions_c::get_declaration(symbol_c *root) {
+ text = "";
+ if (NULL != root) {
+ root->accept(*this);
+ }
+
+ return text;
+}
+
+void *create_enumtype_conversion_functions_c::visit(identifier_c *symbol) {
+ currentToken = symbol->value;
+
+ return NULL;
+}
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+void *create_enumtype_conversion_functions_c::visit(enumerated_type_declaration_c *symbol) {
+ std::string enumerateName;
+ std::string functionName;
+ std::list <std::string> enumerateValues;
+
+ symbol->enumerated_type_name->accept(*this);
+ enumerateName = currentToken;
+
+ symbol->enumerated_spec_init->accept(*this);
+ enumerateValues = currentTokenList;
+
+ printStringToEnum (enumerateName, enumerateValues);
+ printEnumToString (enumerateName, enumerateValues);
+ for (size_t s = 8; s <= 64; s*= 2) {
+ printIntegerToEnum (enumerateName, enumerateValues, true , s);
+ printEnumToInteger (enumerateName, enumerateValues, true , s);
+ printIntegerToEnum (enumerateName, enumerateValues, false, s);
+ printEnumToInteger (enumerateName, enumerateValues, false, s);
+ }
+ if (debug) std::cout << text << std::endl;
+
+ return NULL;
+}
+
+void *create_enumtype_conversion_functions_c::visit(enumerated_value_list_c *symbol) {
+ list_c *list;
+
+ currentTokenList.clear();
+ list = (list_c *)symbol;
+ for (int i = 0; i < list->n; i++) {
+ list->elements[i]->accept(*this);
+ currentTokenList.push_back(currentToken);
+ }
+
+ return NULL;
+}
+
+/*
+ * getIntegerName function generate a integer data name from signed and size.
+ */
+std::string create_enumtype_conversion_functions_c::getIntegerName(bool isSigned, size_t size) {
+ std::string integerType = "";
+ if (! isSigned) {
+ integerType = "U";
+ }
+ switch(size) {
+ case 8 : integerType += "S"; break;
+ case 16: break;
+ case 32: integerType += "D"; break;
+ case 64: integerType += "L"; break;
+ default: break;
+ }
+ integerType +="INT";
+
+ return integerType;
+}
+
+/*
+ * printStringToEnum function print conversion function from STRING to <ENUM>:
+ * ST Output:
+ *
+
+ FUNCTION STRING_TO_<ENUM> : <ENUM>
+ VAR_INPUT
+ IN: STRING;
+ END_VAR
+ IF IN = '<ENUM.VALUE_1>' THEN
+ STRING_TO_<ENUM> := <ENUM.VALUE_1>;
+ RETURN;
+ END_IF;
+ ...
+ IF IN = '<ENUM.VALU_N>' THEN
+ STRING_TO_<ENUM> := <ENUM.VALUE_N>;
+ RETURN;
+ END_IF;
+ END_FUNCTION
+
+ Note: if you change code below remember to update this comment.
+ */
+void create_enumtype_conversion_functions_c::printStringToEnum (std::string &enumerateName, std::list<std::string> &enumerateValues) {
+ std::list <std::string>::const_iterator itr;
+ std::string functionName;
+
+ functionName = "STRING_TO_" + enumerateName;
+ text += "FUNCTION " + functionName + " : " + enumerateName;
+ text += "\nVAR_INPUT\nIN : STRING;\nEND_VAR\n";
+ for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) {
+ std::string value = *itr;
+ text += "IF IN = '" + value + "' THEN\n";
+ text += " " + functionName + " := " + value + ";\n";
+ text += " RETURN;\n";
+ text += "END_IF;\n";
+ }
+ text += "END_FUNCTION\n\n";
+}
+
+/*
+ * printEnumToString function print conversion function from <ENUM> to STRING:
+ * ST Output:
+ *
+
+ FUNCTION <ENUM>_TO_STRING : STRING
+ VAR_INPUT
+ IN: <ENUM>;
+ END_VAR
+ IF IN = <ENUM.VALUE_1> THEN
+ <ENUM>_TO_STRING := '<ENUM.VALUE_1>';
+ RETURN;
+ END_IF;
+ ...
+ IF IN = <ENUM.VALUE_N> THEN
+ <ENUM>_TO_STRING := '<ENUM.VALUE_N>';
+ RETURN;
+ END_IF;
+ END_FUNCTION
+
+ Note: if you change code below remember to update this comment.
+ */
+void create_enumtype_conversion_functions_c::printEnumToString (std::string &enumerateName, std::list<std::string> &enumerateValues) {
+ std::list <std::string>::const_iterator itr;
+ std::string functionName;
+
+ functionName = enumerateName + "_TO_STRING";
+ text += "FUNCTION " + functionName + " : STRING";
+ text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n";
+ for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) {
+ std::string value = *itr;
+ text += "IF IN = " + value + " THEN\n";
+ text += " " + functionName + " := '" + value + "';\n";
+ text += " RETURN;\n";
+ text += "END_IF;\n";
+ }
+ text += "END_FUNCTION\n\n";
+}
+
+/*
+ * printIntegerToEnum function print conversion function from <INTEGER> to <ENUM>:
+ * ST Output:
+ *
+
+ FUNCTION <INTEGER>_TO_<ENUM> : <ENUM>
+ VAR_INPUT
+ IN: <INTEGER>;
+ END_VAR
+ IF IN = 1 THEN
+ <INTEGER>_TO_<ENUM> := <ENUM.VALUE_1>;
+ RETURN;
+ END_IF;
+ ...
+ IF IN = N THEN
+ <INTEGER>_TO_<ENUM> := <ENUM.VALUE_N>;
+ RETURN;
+ END_IF;
+ END_FUNCTION
+
+ Note: if you change code below remember to update this comment.
+ */
+void create_enumtype_conversion_functions_c::printIntegerToEnum (std::string &enumerateName, std::list<std::string> &enumerateValues, bool isSigned, size_t size) {
+ std::list <std::string>::const_iterator itr;
+ std::string functionName;
+ std::string integerType;
+ int count;
+
+ integerType = getIntegerName(isSigned, size);
+ functionName = integerType + "_TO_" + enumerateName;
+ text += "FUNCTION " + functionName + " : " + enumerateName;
+ text += "\nVAR_INPUT\nIN : " + integerType + ";\nEND_VAR\n";
+ count = 0;
+ for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) {
+ std::string value = *itr;
+ std::stringstream out;
+ out << count;
+ text += "IF IN = " + out.str() + " THEN\n";
+ text += " " + functionName + " := " + value + ";\n";
+ text += " RETURN;\n";
+ text += "END_IF;\n";
+ count++;
+ }
+ text += "END_FUNCTION\n\n";
+}
+
+/*
+ * printEnumToInteger function print conversion function from <ENUM> to <INTEGER>:
+ * ST Output:
+ *
+
+ FUNCTION <ENUM>_TO_<INTEGER> : <INTEGER>
+ VAR_INPUT
+ IN: <INTEGER>;
+ END_VAR
+ IF IN = <ENUM.VALUE_1> THEN
+ <ENUM>_TO_<INTEGER> := 1;
+ RETURN;
+ END_IF;
+ ...
+ IF IN = <ENUM.VALUE_N> THEN
+ <ENUM>_TO_<INTEGER> := N;
+ RETURN;
+ END_IF;
+ END_FUNCTION
+
+ Note: if you change code below remember to update this comment.
+ */
+void create_enumtype_conversion_functions_c::printEnumToInteger (std::string &enumerateName, std::list<std::string> &enumerateValues, bool isSigned, size_t size) {
+ std::list <std::string>::const_iterator itr;
+ std::string functionName;
+ std::string integerType;
+ int count;
+
+ integerType = getIntegerName(isSigned, size);
+ functionName = enumerateName + "_TO_" + integerType;
+ text += "FUNCTION " + functionName + " : " + integerType;
+ text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n";
+ count = 0;
+ for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) {
+ std::string value = *itr;
+ std::stringstream out;
+ out << count;
+ text += "IF IN = " + value + " THEN\n";
+ text += " " + functionName + " := " + out.str() + ";\n";
+ text += " RETURN;\n";
+ text += "END_IF;\n";
+ count++;
+ }
+ text += "END_FUNCTION\n\n";
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage1_2/create_enumtype_conversion_functions.hh Thu Nov 22 19:26:56 2012 +0000
@@ -0,0 +1,78 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it)
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+/*
+ * create_enumtype_conversion_functions_c generates ST conversion functions source code for
+ * enumerate user defined data types.
+ *
+ */
+
+#ifndef _CREATE_ENUMTYPE_CONVERSION_FUNCTIONS_HH
+#define _CREATE_ENUMTYPE_CONVERSION_FUNCTIONS_HH
+
+#include <string>
+#include <list>
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+
+class create_enumtype_conversion_functions_c: public iterator_visitor_c {
+ public:
+ explicit create_enumtype_conversion_functions_c(symbol_c *ignore);
+ virtual ~create_enumtype_conversion_functions_c(void);
+ std::string &get_declaration(symbol_c *root);
+
+ const static char *functionDataType [];
+
+ void *visit(identifier_c *symbol);
+ /**********************/
+ /* B 1.3 - Data types */
+ /**********************/
+ /********************************/
+ /* B 1.3.3 - Derived data types */
+ /********************************/
+ void *visit(enumerated_type_declaration_c *symbol);
+ void *visit(enumerated_value_list_c *symbol);
+
+ private:
+ std::string text;
+ std::string currentToken;
+ std::list <std::string> currentTokenList;
+ std::string getIntegerName(bool isSigned, size_t size);
+ void printStringToEnum (std::string &enumerateName, std::list <std::string> &enumerateValues);
+ void printEnumToString (std::string &enumerateName, std::list <std::string> &enumerateValues);
+ void printIntegerToEnum (std::string &enumerateName, std::list <std::string> &enumerateValues, bool isSigned, size_t size);
+ void printEnumToInteger (std::string &enumerateName, std::list <std::string> &enumerateValues, bool isSigned, size_t size);
+};
+
+#endif /* _CREATE_ENUMTYPE_CONVERSION_FUNCTIONS_HH */
--- a/stage1_2/iec_bison.yy Thu Nov 22 19:19:48 2012 +0000
+++ b/stage1_2/iec_bison.yy Thu Nov 22 19:26:56 2012 +0000
@@ -100,7 +100,7 @@
/* The interface through which bison and flex interact. */
#include "stage1_2_priv.hh"
-
+#include "create_enumtype_conversion_functions.hh"
#include "../absyntax_utils/add_en_eno_param_decl.hh" /* required for add_en_eno_param_decl_c */
@@ -203,6 +203,11 @@
*/
extern bool full_token_loc;
+/* A global flag used to tell the parser whether to generate conversion function
+ * for enumerated data types.
+ */
+extern bool conversion_functions_;
+
/* A pointer to the root of the parsing tree that will be generated
* by bison.
*/
@@ -233,6 +238,9 @@
const char *last_filename,
long int last_order,
const char *additional_error_msg);
+
+/* Create entry in symbol table for function conversion data type*/
+void add_enumtype_conversion_functions(const char * dname);
%}
@@ -2704,7 +2712,13 @@
* and include the library_element_symtable.insert(...) code in the rule actions!
*/
identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);}
- {$$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, NULL, locloc(@3)), locloc(@$));}
+ {
+ $$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, NULL, locloc(@3)), locloc(@$));
+ if (conversion_functions_) {
+ const char *name = ((identifier_c *)$1)->value;
+ add_enumtype_conversion_functions(name);
+ }
+ }
| identifier ':' enumerated_specification {library_element_symtable.insert($1, prev_declared_enumerated_type_name_token);} ASSIGN enumerated_value
{$$ = new enumerated_type_declaration_c($1, new enumerated_spec_init_c($3, $6, locf(@3), locl(@6)), locloc(@$));}
/* ERROR_CHECK_BEGIN */
@@ -8340,5 +8354,84 @@
return 0;
}
-
-
+/* Create a tmp file from a char buffer. */
+FILE *ftmpopen (void *buf, size_t size, const char *opentype)
+{
+ FILE *f;
+ f = tmpfile();
+ fwrite(buf, 1, size, f);
+ rewind(f);
+ return f;
+}
+
+/* sstage2__ function allow to parse a ST code inside a string.
+ * We use this function to add into AST auto generated code like enum conversion functions.
+ * This appoach allow us to write future changes code indipendetly and to check generate code
+ * during developing.
+ */
+int sstage2__(const char *text,
+ symbol_c **tree_root_ref,
+ bool full_token_loc_ /* error messages specify full token location */
+ ) {
+
+ FILE *in_file = NULL;
+
+ if((in_file = ftmpopen((void *)text, strlen(text), "r")) == NULL) {
+ perror("Error creating temp file.");
+ return -1;
+ }
+
+ /* now parse the input file... */
+ #if YYDEBUG
+ yydebug = 1;
+ #endif
+ yyin = in_file;
+
+ /* We turn on "allow_function_overloading" flag to disable some checks.
+ * In detail when we add to symboltable a symbol already processed we
+ * don't want to get any error.
+ */
+
+ allow_function_overloading = true;
+ allow_extensible_function_parameters = false;
+ full_token_loc = full_token_loc_;
+ current_filename = "built-in";
+ current_tracking = GetNewTracking(yyin);
+ {int res;
+ if ((res = yyparse()) != 0) {
+ fprintf (stderr, "\nParsing failed because of too many consecutive syntax errors. Bailing out!\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (yynerrs > 0) {
+ fprintf (stderr, "\n%d error(s) found. Bailing out!\n", yynerrs /* global variable */);
+ exit(EXIT_FAILURE);
+ }
+
+ if (tree_root_ref != NULL)
+ *tree_root_ref = tree_root;
+
+ fclose(in_file);
+ return 0;
+}
+
+
+/* Create entry in symbol table for function conversion data type*/
+void add_enumtype_conversion_functions(const char * dname) {
+ std::string strname;
+ std::string tmp;
+
+ strname = dname;
+ for (int i = 0; create_enumtype_conversion_functions_c::functionDataType[i] != NULL; i++) {
+ tmp = strname + std::string("_TO_") + create_enumtype_conversion_functions_c::functionDataType[i];
+ library_element_symtable.insert(tmp.c_str(), prev_declared_derived_function_name_token);
+
+ tmp = create_enumtype_conversion_functions_c::functionDataType[i] + std::string("_TO_") + strname;
+ library_element_symtable.insert(tmp.c_str(), prev_declared_derived_function_name_token);
+ }
+}
+
+
+
+
--- a/stage1_2/stage1_2.cc Thu Nov 22 19:19:48 2012 +0000
+++ b/stage1_2/stage1_2.cc Thu Nov 22 19:26:56 2012 +0000
@@ -46,7 +46,7 @@
#include "stage1_2.hh"
#include "iec_bison.h"
#include "stage1_2_priv.hh"
-
+#include "create_enumtype_conversion_functions.hh"
@@ -66,15 +66,22 @@
/******************************************************/
-/* whether we are suporting safe extensions */
+/* whether we are supporting safe extensions */
/* as defined in PLCopen - Technical Committee 5 */
/* Safety Software Technical Specification, */
/* Part 1: Concepts and Function Blocks, */
-/* Version 1.0 – Official Release */
+/* Version 1.0 – Official Release */
/******************************************************/
bool safe_extensions_ = false;
bool get_opt_safe_extensions() {return safe_extensions_;}
+/******************************************************/
+/* whether we are supporting conversion functions */
+/* for enumerate data types */
+/******************************************************/
+bool conversion_functions_ = false;
+
+
/****************************************************/
/* Controlling the entry to the body_state in flex. */
/****************************************************/
@@ -285,6 +292,11 @@
bool full_token_loc /* error messages specify full token location */
);
+int sstage2__(const char *text,
+ symbol_c **tree_root_ref,
+ bool full_token_loc /* error messages specify full token location */
+ );
+
int stage1_2(const char *filename, symbol_c **tree_root_ref, stage1_2_options_t options) {
/* NOTE: we only call stage2 (bison - syntax analysis) directly, as stage 2 will itself call stage1 (flex - lexical analysis)
@@ -297,8 +309,16 @@
* These callback functions will get their data from local (to this file) global variables...
* We now set those variables...
*/
+
safe_extensions_ = options.safe_extensions;
-
- return stage2__(filename, options.includedir, tree_root_ref, options.full_token_loc);
-}
-
+ conversion_functions_ = options.conversion_functions;
+ int ret = stage2__(filename, options.includedir, tree_root_ref, options.full_token_loc);
+
+ if (conversion_functions_) {
+ create_enumtype_conversion_functions_c create_enumtype_conversion_functions_c(*tree_root_ref);
+ std::string source_code = create_enumtype_conversion_functions_c.get_declaration(*tree_root_ref);
+ ret = sstage2__(source_code.c_str(), tree_root_ref, false);
+ }
+ return ret;
+}
+
--- a/stage1_2/stage1_2.hh Thu Nov 22 19:19:48 2012 +0000
+++ b/stage1_2/stage1_2.hh Thu Nov 22 19:26:56 2012 +0000
@@ -60,6 +60,8 @@
/* error messages specify full token location */
bool full_token_loc;
/* Include directory, where included files will be searched for... */
+ bool conversion_functions;
+ /* Create a conversion function for derived datatype */
const char *includedir;
} stage1_2_options_t;
--- a/stage3/stage3.hh Thu Nov 22 19:19:48 2012 +0000
+++ b/stage3/stage3.hh Thu Nov 22 19:26:56 2012 +0000
@@ -30,9 +30,12 @@
*
*/
+#ifndef _STAGE3_HH
+#define _STAGE3_HH
#include "../util/symtable.hh"
int stage3(symbol_c *tree_root);
+#endif /* _STAGE3_HH */
--- a/stage4/stage4.hh Thu Nov 22 19:19:48 2012 +0000
+++ b/stage4/stage4.hh Thu Nov 22 19:26:56 2012 +0000
@@ -36,6 +36,8 @@
* by each specific version of the 4th stage.
*/
+#ifndef _STAGE4_HH
+#define _STAGE4_HH
#include "../absyntax/absyntax.hh"
@@ -100,6 +102,6 @@
+int stage4(symbol_c *tree_root, const char *builddir);
-
-int stage4(symbol_c *tree_root);
+#endif /* _STAGE4_HH */