2 from xml.dom import minidom |
2 from xml.dom import minidom |
3 import cPickle |
3 import cPickle |
4 |
4 |
5 from xmlclass import * |
5 from xmlclass import * |
6 |
6 |
7 from CFileEditor import CFileEditor |
7 from PLCControler import UndoBuffer |
8 from PLCControler import UndoBuffer, LOCATION_CONFNODE, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT |
8 from editors.CodeFileEditor import SECTIONS_NAMES |
9 |
9 |
10 CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd")) |
10 CodeFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "code_file.xsd")) |
11 |
11 |
12 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", |
12 class CodeFile: |
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" ?> |
|
18 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
19 <xsd:element name="CExtension"> |
|
20 <xsd:complexType> |
|
21 <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/> |
|
22 <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/> |
|
23 </xsd:complexType> |
|
24 </xsd:element> |
|
25 </xsd:schema> |
|
26 """ |
|
27 EditorType = CFileEditor |
|
28 |
13 |
29 def __init__(self): |
14 def __init__(self): |
30 filepath = self.CFileName() |
15 filepath = self.CodeFileName() |
31 |
16 |
32 self.CFile = CFileClasses["CFile"]() |
17 self.CodeFile = CodeFileClasses["CodeFile"]() |
33 if os.path.isfile(filepath): |
18 if os.path.isfile(filepath): |
34 xmlfile = open(filepath, 'r') |
19 xmlfile = open(filepath, 'r') |
35 tree = minidom.parse(xmlfile) |
20 tree = minidom.parse(xmlfile) |
36 xmlfile.close() |
21 xmlfile.close() |
37 |
22 |
38 for child in tree.childNodes: |
23 for child in tree.childNodes: |
39 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CFile": |
24 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "CodeFile": |
40 self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) |
25 self.CodeFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) |
41 self.CreateCFileBuffer(True) |
26 self.CreateCodeFileBuffer(True) |
42 else: |
27 else: |
43 self.CreateCFileBuffer(False) |
28 self.CreateCodeFileBuffer(False) |
44 self.OnCTNSave() |
29 self.OnCTNSave() |
45 |
|
46 def GetIconName(self): |
|
47 return "Cfile" |
|
48 |
|
49 def CFileName(self): |
|
50 return os.path.join(self.CTNPath(), "cfile.xml") |
|
51 |
30 |
52 def GetBaseTypes(self): |
31 def GetBaseTypes(self): |
53 return self.GetCTRoot().GetBaseTypes() |
32 return self.GetCTRoot().GetBaseTypes() |
54 |
33 |
55 def GetDataTypes(self, basetypes = False, only_locatables = False): |
34 def GetDataTypes(self, basetypes = False): |
56 return self.GetCTRoot().GetDataTypes(basetypes=basetypes, only_locatables=only_locatables) |
35 return self.GetCTRoot().GetDataTypes(basetypes=basetypes) |
57 |
|
58 def GetSizeOfType(self, type): |
|
59 return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None) |
|
60 |
36 |
61 def SetVariables(self, variables): |
37 def SetVariables(self, variables): |
62 self.CFile.variables.setvariable([]) |
38 self.CodeFile.variables.setvariable([]) |
63 for var in variables: |
39 for var in variables: |
64 variable = CFileClasses["variables_variable"]() |
40 variable = CodeFileClasses["variables_variable"]() |
65 variable.setname(var["Name"]) |
41 variable.setname(var["Name"]) |
66 variable.settype(var["Type"]) |
42 variable.settype(var["Type"]) |
67 variable.setclass(var["Class"]) |
43 variable.setinitial(var["Initial"]) |
68 self.CFile.variables.appendvariable(variable) |
44 self.CodeFile.variables.appendvariable(variable) |
69 |
45 |
70 def GetVariables(self): |
46 def GetVariables(self): |
71 datas = [] |
47 datas = [] |
72 for var in self.CFile.variables.getvariable(): |
48 for var in self.CodeFile.variables.getvariable(): |
73 datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Class" : var.getclass()}) |
49 datas.append({"Name" : var.getname(), "Type" : var.gettype(), "Initial" : var.getinitial()}) |
74 return datas |
50 return datas |
75 |
51 |
76 def SetPartText(self, name, text): |
52 def SetTextParts(self, parts): |
77 if name == "Includes": |
53 for section, code_object in zip( |
78 self.CFile.includes.settext(text) |
54 SECTIONS_NAMES, |
79 elif name == "Globals": |
55 [self.CodeFile.includes, |
80 self.CFile.globals.settext(text) |
56 self.CodeFile.globals, |
81 elif name == "Init": |
57 self.CodeFile.initFunction, |
82 self.CFile.initFunction.settext(text) |
58 self.CodeFile.cleanUpFunction, |
83 elif name == "CleanUp": |
59 self.CodeFile.retrieveFunction, |
84 self.CFile.cleanUpFunction.settext(text) |
60 self.CodeFile.publishFunction]): |
85 elif name == "Retrieve": |
61 code_object.settext(parts[section]) |
86 self.CFile.retrieveFunction.settext(text) |
|
87 elif name == "Publish": |
|
88 self.CFile.publishFunction.settext(text) |
|
89 |
62 |
90 def GetPartText(self, name): |
63 def GetTextParts(self): |
91 if name == "Includes": |
64 parts = {} |
92 return self.CFile.includes.gettext() |
65 for section, code_object in zip( |
93 elif name == "Globals": |
66 SECTIONS_NAMES, |
94 return self.CFile.globals.gettext() |
67 [self.CodeFile.includes, |
95 elif name == "Init": |
68 self.CodeFile.globals, |
96 return self.CFile.initFunction.gettext() |
69 self.CodeFile.initFunction, |
97 elif name == "CleanUp": |
70 self.CodeFile.cleanUpFunction, |
98 return self.CFile.cleanUpFunction.gettext() |
71 self.CodeFile.retrieveFunction, |
99 elif name == "Retrieve": |
72 self.CodeFile.publishFunction]): |
100 return self.CFile.retrieveFunction.gettext() |
73 parts[section] = code_object.gettext() |
101 elif name == "Publish": |
74 return parts |
102 return self.CFile.publishFunction.gettext() |
|
103 return "" |
|
104 |
75 |
105 def CTNTestModified(self): |
76 def CTNTestModified(self): |
106 return self.ChangesToSave or not self.CFileIsSaved() |
77 return self.ChangesToSave or not self.CodeFileIsSaved() |
107 |
78 |
108 def OnCTNSave(self, from_project_path=None): |
79 def OnCTNSave(self, from_project_path=None): |
109 filepath = self.CFileName() |
80 filepath = self.CodeFileName() |
110 |
81 |
111 text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" |
82 text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" |
112 extras = {"xmlns":"http://www.w3.org/2001/XMLSchema", |
83 extras = {"xmlns":"http://www.w3.org/2001/XMLSchema", |
113 "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance", |
84 "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance", |
114 "xsi:schemaLocation" : "cext_xsd.xsd"} |
85 "xsi:schemaLocation" : "codefile.xsd"} |
115 text += self.CFile.generateXMLText("CFile", 0, extras) |
86 text += self.CodeFile.generateXMLText("CodeFile", 0, extras) |
116 |
87 |
117 xmlfile = open(filepath,"w") |
88 xmlfile = open(filepath,"w") |
118 xmlfile.write(text.encode("utf-8")) |
89 xmlfile.write(text.encode("utf-8")) |
119 xmlfile.close() |
90 xmlfile.close() |
120 |
91 |
121 self.MarkCFileAsSaved() |
92 self.MarkCodeFileAsSaved() |
122 return True |
93 return True |
123 |
94 |
124 def CTNGlobalInstances(self): |
95 def CTNGlobalInstances(self): |
125 current_location = self.GetCurrentLocation() |
96 current_location = self.GetCurrentLocation() |
126 return [("%s_%s" % ( |
97 return [(variable.getname(), |
127 variable.getname(),"_".join(map(str, current_location))), |
98 variable.gettype(), |
128 variable.gettype()) |
99 variable.getinitial()) |
129 for variable in self.CFile.variables.variable] |
100 for variable in self.CodeFile.variables.variable] |
130 |
|
131 def CTNGenerate_C(self, buildpath, locations): |
|
132 """ |
|
133 Generate C code |
|
134 @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5) |
|
135 @param locations: List of complete variables locations \ |
|
136 [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) |
|
137 "NAME" : name of the variable (generally "__IW0_1_2" style) |
|
138 "DIR" : direction "Q","I" or "M" |
|
139 "SIZE" : size "X", "B", "W", "D", "L" |
|
140 "LOC" : tuple of interger for IEC location (0,1,2,...) |
|
141 }, ...] |
|
142 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
|
143 """ |
|
144 current_location = self.GetCurrentLocation() |
|
145 # define a unique name for the generated C file |
|
146 location_str = "_".join(map(str, current_location)) |
|
147 |
|
148 text = "/* Code generated by Beremiz c_ext confnode */\n\n" |
|
149 text += "#include <stdio.h>" |
|
150 |
|
151 # Adding includes |
|
152 text += "/* User includes */\n" |
|
153 text += self.CFile.includes.gettext() |
|
154 text += "\n" |
|
155 |
|
156 text += '#include "iec_types_all.h"' |
|
157 |
|
158 # Adding variables |
|
159 base_types = self.GetCTRoot().GetBaseTypes() |
|
160 config = self.GetCTRoot().GetProjectConfigNames()[0] |
|
161 text += "/* User variables reference */\n" |
|
162 for variable in self.CFile.variables.variable: |
|
163 var_infos = { |
|
164 "name": variable.getname(), |
|
165 "global": "%s__%s_%s" % (config.upper(), |
|
166 variable.getname().upper(), |
|
167 location_str), |
|
168 "type": "__IEC_%s_t" % variable.gettype()} |
|
169 text += "extern %(type)s %(global)s;\n" % var_infos |
|
170 text += "#define %(name)s %(global)s.value\n" % var_infos |
|
171 text += "\n" |
|
172 |
|
173 # Adding user global variables and routines |
|
174 text += "/* User internal user variables and routines */\n" |
|
175 text += self.CFile.globals.gettext() |
|
176 |
|
177 # Adding Beremiz confnode functions |
|
178 text += "/* Beremiz confnode functions */\n" |
|
179 text += "int __init_%s(int argc,char **argv)\n{\n"%location_str |
|
180 text += self.CFile.initFunction.gettext() |
|
181 text += " return 0;\n" |
|
182 text += "\n}\n\n" |
|
183 |
|
184 text += "void __cleanup_%s(void)\n{\n"%location_str |
|
185 text += self.CFile.cleanUpFunction.gettext() |
|
186 text += "\n}\n\n" |
|
187 |
|
188 text += "void __retrieve_%s(void)\n{\n"%location_str |
|
189 text += self.CFile.retrieveFunction.gettext() |
|
190 text += "\n}\n\n" |
|
191 |
|
192 text += "void __publish_%s(void)\n{\n"%location_str |
|
193 text += self.CFile.publishFunction.gettext() |
|
194 text += "\n}\n\n" |
|
195 |
|
196 Gen_Cfile_path = os.path.join(buildpath, "CFile_%s.c"%location_str) |
|
197 cfile = open(Gen_Cfile_path,'w') |
|
198 cfile.write(text) |
|
199 cfile.close() |
|
200 |
|
201 matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()) |
|
202 |
|
203 return [(Gen_Cfile_path, str(self.CExtension.getCFLAGS() + matiec_flags))],str(self.CExtension.getLDFLAGS()),True |
|
204 |
|
205 |
101 |
206 #------------------------------------------------------------------------------- |
102 #------------------------------------------------------------------------------- |
207 # Current Buffering Management Functions |
103 # Current Buffering Management Functions |
208 #------------------------------------------------------------------------------- |
104 #------------------------------------------------------------------------------- |
209 |
105 |
210 """ |
106 """ |
211 Return a copy of the cfile model |
107 Return a copy of the codefile model |
212 """ |
108 """ |
213 def Copy(self, model): |
109 def Copy(self, model): |
214 return cPickle.loads(cPickle.dumps(model)) |
110 return cPickle.loads(cPickle.dumps(model)) |
215 |
111 |
216 def CreateCFileBuffer(self, saved): |
112 def CreateCodeFileBuffer(self, saved): |
217 self.Buffering = False |
113 self.Buffering = False |
218 self.CFileBuffer = UndoBuffer(cPickle.dumps(self.CFile), saved) |
114 self.CodeFileBuffer = UndoBuffer(cPickle.dumps(self.CodeFile), saved) |
219 |
115 |
220 def BufferCFile(self): |
116 def BufferCodeFile(self): |
221 self.CFileBuffer.Buffering(cPickle.dumps(self.CFile)) |
117 self.CodeFileBuffer.Buffering(cPickle.dumps(self.CodeFile)) |
222 |
118 |
223 def StartBuffering(self): |
119 def StartBuffering(self): |
224 self.Buffering = True |
120 self.Buffering = True |
225 |
121 |
226 def EndBuffering(self): |
122 def EndBuffering(self): |
227 if self.Buffering: |
123 if self.Buffering: |
228 self.CFileBuffer.Buffering(cPickle.dumps(self.CFile)) |
124 self.CodeFileBuffer.Buffering(cPickle.dumps(self.CodeFile)) |
229 self.Buffering = False |
125 self.Buffering = False |
230 |
126 |
231 def MarkCFileAsSaved(self): |
127 def MarkCodeFileAsSaved(self): |
232 self.EndBuffering() |
128 self.EndBuffering() |
233 self.CFileBuffer.CurrentSaved() |
129 self.CodeFileBuffer.CurrentSaved() |
234 |
130 |
235 def CFileIsSaved(self): |
131 def CodeFileIsSaved(self): |
236 return self.CFileBuffer.IsCurrentSaved() and not self.Buffering |
132 return self.CodeFileBuffer.IsCurrentSaved() and not self.Buffering |
237 |
133 |
238 def LoadPrevious(self): |
134 def LoadPrevious(self): |
239 self.EndBuffering() |
135 self.EndBuffering() |
240 self.CFile = cPickle.loads(self.CFileBuffer.Previous()) |
136 self.CodeFile = cPickle.loads(self.CodeFileBuffer.Previous()) |
241 |
137 |
242 def LoadNext(self): |
138 def LoadNext(self): |
243 self.CFile = cPickle.loads(self.CFileBuffer.Next()) |
139 self.CodeFile = cPickle.loads(self.CodeFileBuffer.Next()) |
244 |
140 |
245 def GetBufferState(self): |
141 def GetBufferState(self): |
246 first = self.CFileBuffer.IsFirst() and not self.Buffering |
142 first = self.CodeFileBuffer.IsFirst() and not self.Buffering |
247 last = self.CFileBuffer.IsLast() |
143 last = self.CodeFileBuffer.IsLast() |
248 return not first, not last |
144 return not first, not last |
249 |
145 |