conti@748: /* conti@748: * matiec - a compiler for the programming languages defined in IEC 61131-3 conti@748: * conti@748: * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt) conti@748: * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it) conti@748: * conti@748: * conti@748: * This program is free software: you can redistribute it and/or modify conti@748: * it under the terms of the GNU General Public License as published by conti@748: * the Free Software Foundation, either version 3 of the License, or conti@748: * (at your option) any later version. conti@748: * conti@748: * This program is distributed in the hope that it will be useful, conti@748: * but WITHOUT ANY WARRANTY; without even the implied warranty of conti@748: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the conti@748: * GNU General Public License for more details. conti@748: * conti@748: * You should have received a copy of the GNU General Public License conti@748: * along with this program. If not, see . conti@748: * conti@748: * conti@748: * This code is made available on the understanding that it will not be conti@748: * used in safety-critical situations without a full and competent review. conti@748: */ conti@748: conti@748: /* conti@748: * An IEC 61131-3 compiler. conti@748: * conti@748: * Based on the conti@748: * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) conti@748: * conti@748: */ conti@748: conti@748: #include conti@748: #include "create_enumtype_conversion_functions.hh" conti@748: conti@748: /* set to 1 to see debug info during execution */ conti@748: static const int debug = 0; conti@748: conti@748: /* conti@748: * functionDataType array contains all supported data type conversion. conti@748: */ conti@748: const char *create_enumtype_conversion_functions_c::functionDataType[] = { conti@748: "STRING", conti@748: "SINT" , conti@748: "INT" , conti@748: "DINT" , conti@748: "LINT" , conti@748: "USINT" , conti@748: "UNIT" , conti@748: "UDINT" , conti@748: "ULINT" , conti@748: NULL conti@748: }; conti@748: conti@748: create_enumtype_conversion_functions_c::create_enumtype_conversion_functions_c(symbol_c *ignore) { conti@748: conti@748: } conti@748: conti@748: create_enumtype_conversion_functions_c::~create_enumtype_conversion_functions_c(void) { conti@748: conti@748: } conti@748: conti@748: std::string &create_enumtype_conversion_functions_c::get_declaration(symbol_c *root) { conti@748: text = ""; conti@748: if (NULL != root) { conti@748: root->accept(*this); conti@748: } conti@748: conti@748: return text; conti@748: } conti@748: conti@748: void *create_enumtype_conversion_functions_c::visit(identifier_c *symbol) { conti@748: currentToken = symbol->value; conti@748: conti@748: return NULL; conti@748: } conti@748: conti@748: /**********************/ conti@748: /* B 1.3 - Data types */ conti@748: /**********************/ conti@748: /********************************/ conti@748: /* B 1.3.3 - Derived data types */ conti@748: /********************************/ conti@748: void *create_enumtype_conversion_functions_c::visit(enumerated_type_declaration_c *symbol) { conti@748: std::string enumerateName; conti@748: std::string functionName; conti@748: std::list enumerateValues; conti@748: conti@748: symbol->enumerated_type_name->accept(*this); conti@748: enumerateName = currentToken; conti@748: conti@748: symbol->enumerated_spec_init->accept(*this); conti@748: enumerateValues = currentTokenList; conti@748: conti@748: printStringToEnum (enumerateName, enumerateValues); conti@748: printEnumToString (enumerateName, enumerateValues); conti@748: for (size_t s = 8; s <= 64; s*= 2) { conti@748: printIntegerToEnum (enumerateName, enumerateValues, true , s); conti@748: printEnumToInteger (enumerateName, enumerateValues, true , s); conti@748: printIntegerToEnum (enumerateName, enumerateValues, false, s); conti@748: printEnumToInteger (enumerateName, enumerateValues, false, s); conti@748: } conti@748: if (debug) std::cout << text << std::endl; conti@748: conti@748: return NULL; conti@748: } conti@748: conti@748: void *create_enumtype_conversion_functions_c::visit(enumerated_value_list_c *symbol) { conti@748: list_c *list; conti@748: conti@748: currentTokenList.clear(); conti@748: list = (list_c *)symbol; conti@748: for (int i = 0; i < list->n; i++) { conti@748: list->elements[i]->accept(*this); conti@748: currentTokenList.push_back(currentToken); conti@748: } conti@748: conti@748: return NULL; conti@748: } conti@748: conti@748: /* conti@748: * getIntegerName function generate a integer data name from signed and size. conti@748: */ conti@748: std::string create_enumtype_conversion_functions_c::getIntegerName(bool isSigned, size_t size) { conti@748: std::string integerType = ""; conti@748: if (! isSigned) { conti@748: integerType = "U"; conti@748: } conti@748: switch(size) { conti@748: case 8 : integerType += "S"; break; conti@748: case 16: break; conti@748: case 32: integerType += "D"; break; conti@748: case 64: integerType += "L"; break; conti@748: default: break; conti@748: } conti@748: integerType +="INT"; conti@748: conti@748: return integerType; conti@748: } conti@748: conti@748: /* conti@748: * printStringToEnum function print conversion function from STRING to : conti@748: * ST Output: conti@748: * conti@748: conti@748: FUNCTION STRING_TO_ : conti@748: VAR_INPUT conti@748: IN: STRING; conti@748: END_VAR conti@748: IF IN = '' THEN conti@748: STRING_TO_ := ; conti@748: RETURN; conti@748: END_IF; conti@748: ... conti@748: IF IN = '' THEN conti@748: STRING_TO_ := ; conti@748: RETURN; conti@748: END_IF; conti@748: END_FUNCTION conti@748: conti@748: */ conti@748: void create_enumtype_conversion_functions_c::printStringToEnum (std::string &enumerateName, std::list &enumerateValues) { conti@748: std::list ::const_iterator itr; conti@748: std::string functionName; conti@748: conti@748: functionName = "STRING_TO_" + enumerateName; conti@748: text += "FUNCTION " + functionName + " : " + enumerateName; conti@748: text += "\nVAR_INPUT\nIN : STRING;\nEND_VAR\n"; conti@748: for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { conti@748: std::string value = *itr; conti@748: text += "IF IN = '" + value + "' THEN\n"; conti@748: text += " " + functionName + " := " + value + ";\n"; conti@748: text += " RETURN;\n"; conti@748: text += "END_IF;\n"; conti@748: } conti@748: text += "END_FUNCTION\n\n"; conti@748: } conti@748: conti@748: /* conti@748: * printEnumToString function print conversion function from to STRING: conti@748: * ST Output: conti@748: * conti@748: conti@748: FUNCTION _TO_STRING : STRING conti@748: VAR_INPUT conti@748: IN: ; conti@748: END_VAR conti@748: IF IN = THEN conti@748: _TO_STRING := ''; conti@748: RETURN; conti@748: END_IF; conti@748: ... conti@748: IF IN = THEN conti@748: _TO_STRING := ''; conti@748: RETURN; conti@748: END_IF; conti@748: END_FUNCTION conti@748: conti@748: */ conti@748: void create_enumtype_conversion_functions_c::printEnumToString (std::string &enumerateName, std::list &enumerateValues) { conti@748: std::list ::const_iterator itr; conti@748: std::string functionName; conti@748: conti@748: functionName = enumerateName + "_TO_STRING"; conti@748: text += "FUNCTION " + functionName + " : STRING"; conti@748: text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n"; conti@748: for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { conti@748: std::string value = *itr; conti@748: text += "IF IN = " + value + " THEN\n"; conti@748: text += " " + functionName + " := '" + value + "';\n"; conti@748: text += " RETURN;\n"; conti@748: text += "END_IF;\n"; conti@748: } conti@748: text += "END_FUNCTION\n\n"; conti@748: } conti@748: conti@748: /* conti@748: * printIntegerToEnum function print conversion function from to : conti@748: * ST Output: conti@748: * conti@748: conti@748: FUNCTION _TO_ : conti@748: VAR_INPUT conti@748: IN: ; conti@748: END_VAR conti@748: IF IN = 1 THEN conti@748: _TO_ := ; conti@748: RETURN; conti@748: END_IF; conti@748: ... conti@748: IF IN = N THEN conti@748: _TO_ := ; conti@748: RETURN; conti@748: END_IF; conti@748: END_FUNCTION conti@748: conti@748: */ conti@748: void create_enumtype_conversion_functions_c::printIntegerToEnum (std::string &enumerateName, std::list &enumerateValues, bool isSigned, size_t size) { conti@748: std::list ::const_iterator itr; conti@748: std::string functionName; conti@748: std::string integerType; conti@748: int count; conti@748: conti@748: integerType = getIntegerName(isSigned, size); conti@748: functionName = integerType + "_TO_" + enumerateName; conti@748: text += "FUNCTION " + functionName + " : " + enumerateName; conti@748: text += "\nVAR_INPUT\nIN : " + integerType + ";\nEND_VAR\n"; conti@748: count = 0; conti@748: for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { conti@748: std::string value = *itr; conti@748: std::stringstream out; conti@748: out << count; conti@748: text += "IF IN = " + out.str() + " THEN\n"; conti@748: text += " " + functionName + " := " + value + ";\n"; conti@748: text += " RETURN;\n"; conti@748: text += "END_IF;\n"; conti@748: count++; conti@748: } conti@748: text += "END_FUNCTION\n\n"; conti@748: } conti@748: conti@748: /* conti@748: * printEnumToInteger function print conversion function from to : conti@748: * ST Output: conti@748: * conti@748: conti@748: FUNCTION _TO_ : conti@748: VAR_INPUT conti@748: IN: ; conti@748: END_VAR conti@748: IF IN = THEN conti@748: _TO_ := 1; conti@748: RETURN; conti@748: END_IF; conti@748: ... conti@748: IF IN = THEN conti@748: _TO_ := N; conti@748: RETURN; conti@748: END_IF; conti@748: END_FUNCTION conti@748: conti@748: */ conti@748: void create_enumtype_conversion_functions_c::printEnumToInteger (std::string &enumerateName, std::list &enumerateValues, bool isSigned, size_t size) { conti@748: std::list ::const_iterator itr; conti@748: std::string functionName; conti@748: std::string integerType; conti@748: int count; conti@748: conti@748: integerType = getIntegerName(isSigned, size); conti@748: functionName = enumerateName + "_TO_" + integerType; conti@748: text += "FUNCTION " + functionName + " : " + integerType; conti@748: text += "\nVAR_INPUT\nIN : " + enumerateName + ";\nEND_VAR\n"; conti@748: count = 0; conti@748: for (itr = enumerateValues.begin(); itr != enumerateValues.end(); ++itr) { conti@748: std::string value = *itr; conti@748: std::stringstream out; conti@748: out << count; conti@748: text += "IF IN = " + value + " THEN\n"; conti@748: text += " " + functionName + " := " + out.str() + ";\n"; conti@748: text += " RETURN;\n"; conti@748: text += "END_IF;\n"; conti@748: count++; conti@748: } conti@748: text += "END_FUNCTION\n\n"; conti@748: } conti@748: conti@748: conti@748: