PLCGenerator.py
changeset 1649 3291024e00da
parent 1626 0779c1b18c01
child 1730 64d8f52bc8c8
--- a/PLCGenerator.py	Thu Feb 16 14:34:40 2017 +0500
+++ b/PLCGenerator.py	Thu Feb 16 14:35:12 2017 +0500
@@ -1,26 +1,26 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
-#based on the plcopen standard.
+# This file is part of Beremiz, a Integrated Development Environment for
+# programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
 #
-#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+# Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
 #
-#See COPYING file for copyrights details.
+# See COPYING file for copyrights details.
 #
-#This library 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 2.1 of the License, or (at your option) any later version.
+# 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 2
+# of the License, or (at your option) any later version.
 #
-#This library 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.
+# 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 library; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 from plcopen import PLCOpenParser
 from plcopen.structures import *
@@ -393,6 +393,11 @@
             single = task.getsingle()
             # Single argument if exists
             if single is not None:
+                if len(single) == 0:
+                    msg = _("Source signal has to be defined for single task '{a1}' in resource '{a2}.{a3}'.").\
+                          format(a1 = task.getname(), a2 = config_name, a3 = resource.getname())
+                    raise PLCGenException, msg
+
                 if single[0]=='[' and single[-1]==']' :
                     SNGLKW = "MULTI"
                 else:
@@ -763,7 +768,10 @@
                     content = instance.getconditionContent()
                     if content["type"] == "connection":
                         self.ConnectionTypes[content["value"]] = "BOOL"
-                        for link in content["value"].getconnections():
+                        connections = content["value"].getconnections()
+                        if not connections:
+                            raise PLCGenException, _("SFC transition in POU \"%s\" must be connected.") % self.Name
+                        for link in connections:                        
                             connected = self.GetLinkedConnector(link, body)
                             if connected is not None and not self.ConnectionTypes.has_key(connected):
                                 for related in self.ExtractRelatedConnections(connected):
@@ -775,7 +783,8 @@
                     for element in body.getcontentInstances():
                         if isinstance(element, ConnectorClass) and element.getname() == name:
                             if connector is not None:
-                                raise PLCGenException, _("More than one connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name)
+                                msg = _("More than one connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1 = name, a2 = self.Name)
+                                raise PLCGenException, msg
                             connector = element
                     if connector is not None:
                         undefined = [instance.connectionPointOut, connector.connectionPointIn]
@@ -794,7 +803,8 @@
                             for connection in related:
                                 self.ConnectionTypes[connection] = var_type
                     else:
-                        raise PLCGenException, _("No connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name)
+                        msg = _("No connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1 = name, a2 = self.Name)
+                        raise PLCGenException, msg
                 elif isinstance(instance, BlockClass):
                     block_infos = self.GetBlockType(instance.gettypeName(), "undefined")
                     if block_infos is not None:
@@ -948,7 +958,7 @@
                     if block_infos is None:
                         block_infos = self.GetBlockType(block_type)
                     if block_infos is None:
-                        raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
+                        raise PLCGenException, _("Undefined block type \"{a1}\" in \"{a2}\" POU").format(a1 = block_type, a2 = self.Name)
                     try:
                         self.GenerateBlock(instance, block_infos, body, None)
                     except ValueError, e:
@@ -1088,7 +1098,8 @@
                     self.Program += JoinList([(", ", ())], vars)
                     self.Program += [(");\n", ())]
                 else:
-                    self.Warnings.append(_("\"%s\" function cancelled in \"%s\" POU: No input connected")%(type, self.TagName.split("::")[-1]))
+                    msg = _("\"{a1}\" function cancelled in \"{a2}\" POU: No input connected").format(a1 = type, a2 = self.TagName.split("::")[-1])
+                    self.Warnings.append(msg)
         elif block_infos["type"] == "functionBlock":
             if not self.ComputedBlocks.get(block, False) and not order:
                 self.ComputedBlocks[block] = True
@@ -1177,11 +1188,12 @@
             if output_parameter is None:
                 output_parameter = ""
             if name:
-                blockname = "%s(%s)" % (name, type)
+                blockname = "{a1}({a2})".format(a1 = name, a2 = type)
             else:
                 blockname = type
-            raise ValueError, _("No output %s variable found in block %s in POU %s. Connection must be broken")  % \
-                              (output_parameter, blockname, self.Name)
+            msg = _("No output {a1} variable found in block {a2} in POU {a3}. Connection must be broken").\
+                              format(a1 = output_parameter, a2 = blockname, a3 = self.Name)
+            raise ValueError, msg
 
     def GeneratePaths(self, connections, body, order = False, to_inout = False):
         paths = []
@@ -1199,7 +1211,8 @@
                 if block_infos is None:
                     block_infos = self.GetBlockType(block_type)
                 if block_infos is None:
-                    raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
+                    msg = _("Undefined block type \"{a1}\" in \"{a2}\" POU").format(a1 = block_type, a2 = self.Name)
+                    raise PLCGenException, msg
                 try:
                     paths.append(str(self.GenerateBlock(next, block_infos, body, connection, order, to_inout)))
                 except ValueError, e:
@@ -1214,7 +1227,8 @@
                     for instance in body.getcontentInstances():
                         if isinstance(instance, ConnectorClass) and instance.getname() == name:
                             if connector is not None:
-                                raise PLCGenException, _("More than one connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name)
+                                msg = _("More than one connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1 = name, a2 = self.Name)
+                                raise PLCGenException, msg
                             connector = instance
                     if connector is not None:
                         connections = connector.connectionPointIn.getconnections()
@@ -1224,7 +1238,8 @@
                                 self.ComputedConnectors[name] = expression
                                 paths.append(str(expression))
                     else:
-                        raise PLCGenException, _("No connector found corresponding to \"%s\" continuation in \"%s\" POU")%(name, self.Name)
+                        msg = _("No connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1 = name, a2 = self.Name)
+                        raise PLCGenException, msg
             elif isinstance(next, ContactClass):
                 contact_info = (self.TagName, "contact", next.getlocalId())
                 variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info))
@@ -1372,6 +1387,10 @@
 
     def GenerateSFCJump(self, jump, pou):
         jump_target = jump.gettargetName()
+        if not pou.hasstep(jump_target):
+            pname = pou.getname()
+            msg = _("SFC jump in pou \"{a1}\" refers to non-existent SFC step \"{a2}\"").format( a1 = pname, a2 = jump_target)
+            raise PLCGenException, msg
         if jump.connectionPointIn is not None:
             instances = []
             connections = jump.connectionPointIn.getconnections()
@@ -1576,7 +1595,9 @@
             elif len(transition_infos["from"]) == 1:
                 self.Program += transition_infos["from"][0]
             else:
-                raise PLCGenException, _("Transition with content \"%s\" not connected to a previous step in \"%s\" POU")%(transition_infos["content"], self.Name)
+                msg = _("Transition with content \"{a1}\" not connected to a previous step in \"{a2}\" POU").\
+                      format(a1 = transition_infos["content"], a2 = self.Name)
+                raise PLCGenException, msg
             self.Program += [(" TO ", ())]
             if len(transition_infos["to"]) > 1:
                 self.Program += [("(", ())]
@@ -1585,7 +1606,9 @@
             elif len(transition_infos["to"]) == 1:
                 self.Program += transition_infos["to"][0]
             else:
-                raise PLCGenException, _("Transition with content \"%s\" not connected to a next step in \"%s\" POU")%(transition_infos["content"], self.Name)
+                msg = _("Transition with content \"{a1}\" not connected to a next step in \"{a2}\" POU").\
+                      format(a1 = transition_infos["content"], a2 = self.Name)
+                raise PLCGenException, msg
             self.Program += transition_infos["content"]
             self.Program += [("%sEND_TRANSITION\n\n"%self.CurrentIndent, ())]
             for [(step_name, step_infos)] in transition_infos["to"]: