# HG changeset patch # User Mario de Sousa # Date 1353612416 0 # Node ID 0a5c050d64bb77dc3ac238820a3db73e3dc3db3a # Parent 6ecb387157244f0154e7c9227b157f3b4555eee9# Parent 25f7b35bdff74383c066a4aced19c13a3736dce2 merge diff -r 6ecb38715724 -r 0a5c050d64bb absyntax_utils/Makefile.in --- 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: diff -r 6ecb38715724 -r 0a5c050d64bb absyntax_utils/add_en_eno_param_decl.hh --- 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 */ + diff -r 6ecb38715724 -r 0a5c050d64bb main.cc --- 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 // printf() +#include #include #include -#include // EXIT_FAILURE -#include "absyntax/absyntax.hh" // symbol_c type - -/* A macro for printing out internal parser errors... */ -#include // required for std::cerr +#include +#include +#include + + +#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 // 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 ] [-T ] \n", cmd); + printf("\nsyntax: %s [-h] [-v] [-f] [-s] [-c] [-I ] [-T ] \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; diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/Makefile.am --- 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 diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/Makefile.in --- 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 diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/create_enumtype_conversion_functions.cc --- /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 . + * + * + * 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 +#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 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 : + * ST Output: + * + + FUNCTION STRING_TO_ : + VAR_INPUT + IN: STRING; + END_VAR + IF IN = '' THEN + STRING_TO_ := ; + RETURN; + END_IF; + ... + IF IN = '' THEN + STRING_TO_ := ; + 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 &enumerateValues) { + std::list ::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 to STRING: + * ST Output: + * + + FUNCTION _TO_STRING : STRING + VAR_INPUT + IN: ; + END_VAR + IF IN = THEN + _TO_STRING := ''; + RETURN; + END_IF; + ... + IF IN = THEN + _TO_STRING := ''; + 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 &enumerateValues) { + std::list ::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 to : + * ST Output: + * + + FUNCTION _TO_ : + VAR_INPUT + IN: ; + END_VAR + IF IN = 1 THEN + _TO_ := ; + RETURN; + END_IF; + ... + IF IN = N THEN + _TO_ := ; + 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 &enumerateValues, bool isSigned, size_t size) { + std::list ::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 to : + * ST Output: + * + + FUNCTION _TO_ : + VAR_INPUT + IN: ; + END_VAR + IF IN = THEN + _TO_ := 1; + RETURN; + END_IF; + ... + IF IN = THEN + _TO_ := 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 &enumerateValues, bool isSigned, size_t size) { + std::list ::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"; +} + + + diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/create_enumtype_conversion_functions.hh --- /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 . + * + * + * 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 +#include + +#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 currentTokenList; + std::string getIntegerName(bool isSigned, size_t size); + void printStringToEnum (std::string &enumerateName, std::list &enumerateValues); + void printEnumToString (std::string &enumerateName, std::list &enumerateValues); + void printIntegerToEnum (std::string &enumerateName, std::list &enumerateValues, bool isSigned, size_t size); + void printEnumToInteger (std::string &enumerateName, std::list &enumerateValues, bool isSigned, size_t size); +}; + +#endif /* _CREATE_ENUMTYPE_CONVERSION_FUNCTIONS_HH */ diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/iec_bison.yy --- 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); + } +} + + + + diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/stage1_2.cc --- 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; +} + diff -r 6ecb38715724 -r 0a5c050d64bb stage1_2/stage1_2.hh --- 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; diff -r 6ecb38715724 -r 0a5c050d64bb stage3/stage3.hh --- 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 */ diff -r 6ecb38715724 -r 0a5c050d64bb stage4/stage4.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 */