c_ext/c_ext.py
changeset 1096 c9ace6a881c9
parent 1061 02f371f3e063
child 1097 233681f2a00e
equal deleted inserted replaced
1095:a73fde048749 1096:c9ace6a881c9
     1 import os
     1 import os
     2 from xml.dom import minidom
       
     3 import cPickle
       
     4 
       
     5 from xmlclass import *
       
     6 
     2 
     7 from CFileEditor import CFileEditor
     3 from CFileEditor import CFileEditor
     8 from PLCControler import UndoBuffer, LOCATION_CONFNODE, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT 
     4 from CodeFileTreeNode import CodeFile
     9 
     5 
    10 CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd"))
     6 class CFile(CodeFile):
    11 
       
    12 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
       
    13     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
       
    14     "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
       
    15 
       
    16 class CFile:
       
    17     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
     7     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    18     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     8     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    19       <xsd:element name="CExtension">
     9       <xsd:element name="CExtension">
    20         <xsd:complexType>
    10         <xsd:complexType>
    21           <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
    11           <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
    24       </xsd:element>
    14       </xsd:element>
    25     </xsd:schema>
    15     </xsd:schema>
    26     """
    16     """
    27     EditorType = CFileEditor
    17     EditorType = CFileEditor
    28     
    18     
    29     def __init__(self):
       
    30         filepath = self.CFileName()
       
    31         
       
    32         self.CFile = CFileClasses["CFile"]()
       
    33         if os.path.isfile(filepath):
       
    34             xmlfile = open(filepath, 'r')
       
    35             tree = minidom.parse(xmlfile)
       
    36             xmlfile.close()
       
    37             
       
    38             for child in tree.childNodes:
       
    39                 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile":
       
    40                     self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"])
       
    41                     self.CreateCFileBuffer(True)
       
    42         else:
       
    43             self.CreateCFileBuffer(False)
       
    44             self.OnCTNSave()
       
    45 
       
    46     def GetIconName(self):
    19     def GetIconName(self):
    47         return "Cfile"
    20         return "Cfile"
    48 
    21 
    49     def CFileName(self):
    22     def CodeFileName(self):
    50         return os.path.join(self.CTNPath(), "cfile.xml")
    23         return os.path.join(self.CTNPath(), "cfile.xml")
    51 
       
    52     def GetBaseTypes(self):
       
    53         return self.GetCTRoot().GetBaseTypes()
       
    54 
       
    55     def GetDataTypes(self, basetypes = False, only_locatables = False):
       
    56         return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables)
       
    57 
       
    58     def GetSizeOfType(self, type):
       
    59         return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
       
    60 
       
    61     def SetVariables(self, variables):
       
    62         self.CFile.variables.setvariable([])
       
    63         for var in variables:
       
    64             variable = CFileClasses["variables_variable"]()
       
    65             variable.setname(var["Name"])
       
    66             variable.settype(var["Type"])
       
    67             variable.setclass(var["Class"])
       
    68             self.CFile.variables.appendvariable(variable)
       
    69     
    24     
    70     def GetVariables(self):
       
    71         datas = []
       
    72         for var in self.CFile.variables.getvariable():
       
    73             datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()})
       
    74         return datas
       
    75 
       
    76     def GetVariableLocationTree(self):
       
    77         '''See ConfigTreeNode.GetVariableLocationTree() for a description.'''
       
    78 
       
    79         current_location = ".".join(map(str, self.GetCurrentLocation()))
       
    80         
       
    81         vars = []
       
    82         input = memory = output = 0
       
    83         for var in self.CFile.variables.getvariable():
       
    84             var_size = self.GetSizeOfType(var.gettype())
       
    85             var_location = ""
       
    86             if var.getclass() == "input":
       
    87                 var_class = LOCATION_VAR_INPUT
       
    88                 if var_size is not None:
       
    89                     var_location = "%%I%s%s.%d"%(var_size, current_location, input)
       
    90                 input += 1
       
    91             elif var.getclass() == "memory":
       
    92                 var_class = LOCATION_VAR_INPUT
       
    93                 if var_size is not None:
       
    94                     var_location = "%%M%s%s.%d"%(var_size, current_location, memory)
       
    95                 memory += 1
       
    96             else:
       
    97                 var_class = LOCATION_VAR_OUTPUT
       
    98                 if var_size is not None:
       
    99                     var_location = "%%Q%s%s.%d"%(var_size, current_location, output)
       
   100                 output += 1
       
   101             vars.append({"name": var.getname(),
       
   102                          "type": var_class,
       
   103                          "size": var_size,
       
   104                          "IEC_type": var.gettype(),
       
   105                          "var_name": var.getname(),
       
   106                          "location": var_location,
       
   107                          "description": "",
       
   108                          "children": []})
       
   109                 
       
   110         return  {"name": self.BaseParams.getName(),
       
   111                 "type": LOCATION_CONFNODE,
       
   112                 "location": self.GetFullIEC_Channel(),
       
   113                 "children": vars}
       
   114 
       
   115     def SetPartText(self, name, text):
       
   116         if name == "Includes":
       
   117             self.CFile.includes.settext(text)
       
   118         elif name == "Globals":
       
   119             self.CFile.globals.settext(text)
       
   120         elif name == "Init":
       
   121             self.CFile.initFunction.settext(text)
       
   122         elif name == "CleanUp":
       
   123             self.CFile.cleanUpFunction.settext(text)
       
   124         elif name == "Retrieve":
       
   125             self.CFile.retrieveFunction.settext(text)
       
   126         elif name == "Publish":
       
   127             self.CFile.publishFunction.settext(text)
       
   128         
       
   129     def GetPartText(self, name):
       
   130         if name == "Includes":
       
   131             return self.CFile.includes.gettext()
       
   132         elif name == "Globals":
       
   133             return self.CFile.globals.gettext()
       
   134         elif name == "Init":
       
   135             return self.CFile.initFunction.gettext()
       
   136         elif name == "CleanUp":
       
   137             return self.CFile.cleanUpFunction.gettext()
       
   138         elif name == "Retrieve":
       
   139             return self.CFile.retrieveFunction.gettext()
       
   140         elif name == "Publish":
       
   141             return self.CFile.publishFunction.gettext()
       
   142         return ""
       
   143                 
       
   144     def CTNTestModified(self):
       
   145         return self.ChangesToSave or not self.CFileIsSaved()    
       
   146 
       
   147     def OnCTNSave(self, from_project_path=None):
       
   148         filepath = self.CFileName()
       
   149         
       
   150         text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
       
   151         extras = {"xmlns":"http://www.w3.org/2001/XMLSchema",
       
   152                   "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
       
   153                   "xsi:schemaLocation" : "cext_xsd.xsd"}
       
   154         text += self.CFile.generateXMLText("CFile", 0, extras)
       
   155 
       
   156         xmlfile = open(filepath,"w")
       
   157         xmlfile.write(text.encode("utf-8"))
       
   158         xmlfile.close()
       
   159         
       
   160         self.MarkCFileAsSaved()
       
   161         return True
       
   162 
       
   163     def CTNGenerate_C(self, buildpath, locations):
    25     def CTNGenerate_C(self, buildpath, locations):
   164         """
    26         """
   165         Generate C code
    27         Generate C code
   166         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
    28         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
   167         @param locations: List of complete variables locations \
    29         @param locations: List of complete variables locations \
   176         current_location = self.GetCurrentLocation()
    38         current_location = self.GetCurrentLocation()
   177         # define a unique name for the generated C file
    39         # define a unique name for the generated C file
   178         location_str = "_".join(map(str, current_location))
    40         location_str = "_".join(map(str, current_location))
   179         
    41         
   180         text = "/* Code generated by Beremiz c_ext confnode */\n\n"
    42         text = "/* Code generated by Beremiz c_ext confnode */\n\n"
       
    43         text += "#include <stdio.h>"
   181         
    44         
   182         # Adding includes
    45         # Adding includes
   183         text += "/* User includes */\n"
    46         text += "/* User includes */\n"
   184         text += self.CFile.includes.gettext()
    47         text += self.CodeFile.includes.gettext()
   185         text += "\n"
    48         text += "\n"
   186         
    49         
   187         text += '#include "iec_types.h"'
    50         text += '#include "iec_types_all.h"'
   188 
    51 
   189         # Adding variables
    52         # Adding variables
   190         vars = []
       
   191         inputs = memories = outputs = 0
       
   192         for variable in self.CFile.variables.variable:
       
   193             var = {"Name" : variable.getname(), "Type" : variable.gettype()}
       
   194             if variable.getclass() == "input":
       
   195                 var["location"] = "__I%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, inputs)
       
   196                 inputs += 1
       
   197             elif variable.getclass() == "memory":
       
   198                 var["location"] = "__M%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, memories)
       
   199                 memories += 1
       
   200             else:
       
   201                 var["location"] = "__Q%s%s_%d"%(self.GetSizeOfType(var["Type"]), location_str, outputs)
       
   202                 outputs += 1
       
   203             vars.append(var)
       
   204         text += "/* Beremiz c_ext confnode user variables definition */\n"
       
   205         base_types = self.GetCTRoot().GetBaseTypes()
    53         base_types = self.GetCTRoot().GetBaseTypes()
   206         for var in vars:
    54         config = self.GetCTRoot().GetProjectConfigNames()[0]
   207             if var["Type"] in base_types:
       
   208                 prefix = "IEC_"
       
   209             else:
       
   210                 prefix = ""
       
   211             text += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
       
   212             text += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
       
   213         text += "/* User variables reference */\n"
    55         text += "/* User variables reference */\n"
   214         for var in vars:
    56         for variable in self.CodeFile.variables.variable:
   215             text += "#define %s beremiz%s\n"%(var["Name"], var["location"])
    57             var_infos = {
       
    58                 "name": variable.getname(),
       
    59                 "global": "%s__%s" % (config.upper(),
       
    60                                       variable.getname().upper()),
       
    61                 "type": "__IEC_%s_t" % variable.gettype()}
       
    62             text += "extern %(type)s %(global)s;\n" % var_infos
       
    63             text += "#define %(name)s %(global)s.value\n" % var_infos
   216         text += "\n"
    64         text += "\n"
   217         
    65         
   218         # Adding user global variables and routines
    66         # Adding user global variables and routines
   219         text += "/* User internal user variables and routines */\n"
    67         text += "/* User internal user variables and routines */\n"
   220         text += self.CFile.globals.gettext()
    68         text += self.CodeFile.globals.gettext()
   221         
    69         
   222         # Adding Beremiz confnode functions
    70         # Adding Beremiz confnode functions
   223         text += "/* Beremiz confnode functions */\n"
    71         text += "/* Beremiz confnode functions */\n"
   224         text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
    72         text += "int __init_%s(int argc,char **argv)\n{\n"%location_str
   225         text += self.CFile.initFunction.gettext()
    73         text += self.CodeFile.initFunction.gettext()
   226         text += "  return 0;\n"
    74         text += "  return 0;\n"
   227         text += "\n}\n\n"
    75         text += "\n}\n\n"
   228         
    76         
   229         text += "void __cleanup_%s(void)\n{\n"%location_str
    77         text += "void __cleanup_%s(void)\n{\n"%location_str
   230         text += self.CFile.cleanUpFunction.gettext()
    78         text += self.CodeFile.cleanUpFunction.gettext()
   231         text += "\n}\n\n"
    79         text += "\n}\n\n"
   232         
    80         
   233         text += "void __retrieve_%s(void)\n{\n"%location_str
    81         text += "void __retrieve_%s(void)\n{\n"%location_str
   234         text += self.CFile.retrieveFunction.gettext()
    82         text += self.CodeFile.retrieveFunction.gettext()
   235         text += "\n}\n\n"
    83         text += "\n}\n\n"
   236         
    84         
   237         text += "void __publish_%s(void)\n{\n"%location_str
    85         text += "void __publish_%s(void)\n{\n"%location_str
   238         text += self.CFile.publishFunction.gettext()
    86         text += self.CodeFile.publishFunction.gettext()
   239         text += "\n}\n\n"
    87         text += "\n}\n\n"
   240         
    88         
   241         Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
    89         Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str)
   242         cfile = open(Gen_Cfile_path,'w')
    90         cfile = open(Gen_Cfile_path,'w')
   243         cfile.write(text)
    91         cfile.write(text)
   245         
    93         
   246         matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
    94         matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
   247         
    95         
   248         return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
    96         return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True
   249 
    97 
   250 
       
   251 #-------------------------------------------------------------------------------
       
   252 #                      Current Buffering Management Functions
       
   253 #-------------------------------------------------------------------------------
       
   254 
       
   255     """
       
   256     Return a copy of the cfile model
       
   257     """
       
   258     def Copy(self, model):
       
   259         return cPickle.loads(cPickle.dumps(model))
       
   260 
       
   261     def CreateCFileBuffer(self, saved):
       
   262         self.Buffering = False
       
   263         self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved)
       
   264 
       
   265     def BufferCFile(self):
       
   266         self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
       
   267     
       
   268     def StartBuffering(self):
       
   269         self.Buffering = True
       
   270         
       
   271     def EndBuffering(self):
       
   272         if self.Buffering:
       
   273             self.CFileBuffer.Buffering(cPickle.dumps(self.CFile))
       
   274             self.Buffering = False
       
   275     
       
   276     def MarkCFileAsSaved(self):
       
   277         self.EndBuffering()
       
   278         self.CFileBuffer.CurrentSaved()
       
   279     
       
   280     def CFileIsSaved(self):
       
   281         return self.CFileBuffer.IsCurrentSaved() and not self.Buffering
       
   282         
       
   283     def LoadPrevious(self):
       
   284         self.EndBuffering()
       
   285         self.CFile = cPickle.loads(self.CFileBuffer.Previous())
       
   286     
       
   287     def LoadNext(self):
       
   288         self.CFile = cPickle.loads(self.CFileBuffer.Next())
       
   289     
       
   290     def GetBufferState(self):
       
   291         first = self.CFileBuffer.IsFirst() and not self.Buffering
       
   292         last = self.CFileBuffer.IsLast()
       
   293         return not first, not last
       
   294