# HG changeset patch
# User Laurent Bessard
# Date 1353016853 -3600
# Node ID 235a9ec83b955459ad15304c3725a277c57d5549
# Parent  3c6ce0a5ab2cef6630875e347474c7f8809d29ff
Adding support for defining specific global variables for ConfTreeNodes
Fix bug when defining function block instances as global variables

diff -r 3c6ce0a5ab2c -r 235a9ec83b95 ConfigTreeNode.py
--- a/ConfigTreeNode.py	Thu Nov 15 22:57:55 2012 +0100
+++ b/ConfigTreeNode.py	Thu Nov 15 23:00:53 2012 +0100
@@ -195,6 +195,18 @@
         shutil.copytree(src_CTNPath, self.CTNPath)
         return True
 
+    def CTNGlobalInstances(self):
+        """
+        @return: [(instance_name, instance_type),...]
+        """
+        return []
+    
+    def _GlobalInstances(self):
+        instances = self.CTNGlobalInstances()
+        for CTNChild in self.IECSortedChildren():
+            instances.extend(CTNChild._GlobalInstances())
+        return instances
+    
     def CTNGenerate_C(self, buildpath, locations):
         """
         Generate C code
diff -r 3c6ce0a5ab2c -r 235a9ec83b95 PLCControler.py
--- a/PLCControler.py	Thu Nov 15 22:57:55 2012 +0100
+++ b/PLCControler.py	Thu Nov 15 23:00:53 2012 +0100
@@ -1476,6 +1476,32 @@
     def GetVariableLocationTree(self):
         return []
 
+    def GetConfNodeGlobalInstances(self):
+        return []
+
+    def GetConfigurationExtraVariables(self):
+        global_vars = []
+        for var_name, var_type in self.GetConfNodeGlobalInstances():
+            tempvar = plcopen.varListPlain_variable()
+            tempvar.setname(var_name)
+            
+            tempvartype = plcopen.dataType()
+            if var_type in self.GetBaseTypes():
+                if var_type == "STRING":
+                    var_type.setcontent({"name" : "string", "value" : plcopen.elementaryTypes_string()})
+                elif var_type == "WSTRING":
+                    var_type.setcontent({"name" : "wstring", "value" : plcopen.elementaryTypes_wstring()})
+                else:
+                    var_type.setcontent({"name" : var_type, "value" : None})
+            else:
+                tempderivedtype = plcopen.derivedTypes_derived()
+                tempderivedtype.setname(var_type)
+                tempvartype.setcontent({"name" : "derived", "value" : tempderivedtype})
+            tempvar.settype(tempvartype)
+            
+            global_vars.append(tempvar)
+        return global_vars
+
     # Function that returns the block definition associated to the block type given
     def GetBlockType(self, type, inputs = None, debug = False):
         result_blocktype = None
@@ -1723,6 +1749,8 @@
             if words[0] == "D":
                 infos = {}
                 datatype = project.getdataType(words[1])
+                if datatype is None:
+                    return None
                 basetype_content = datatype.baseType.getcontent()
                 if basetype_content["value"] is None or basetype_content["name"] in ["string", "wstring"]:
                     infos["type"] = "Directly"
diff -r 3c6ce0a5ab2c -r 235a9ec83b95 PLCGenerator.py
--- a/PLCGenerator.py	Thu Nov 15 22:57:55 2012 +0100
+++ b/PLCGenerator.py	Thu Nov 15 23:00:53 2012 +0100
@@ -268,8 +268,17 @@
                   (configuration.getname(), (tagname, "name")),
                   ("\n", ())]
         var_number = 0
+        
+        varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()]
+        
+        extra_variables = self.Controler.GetConfigurationExtraVariables()
+        if len(extra_variables) > 0:
+            if len(varlists) == 0:
+                varlists = [(plcopen.interface_globalVars(), [])]
+            varlists[-1][1].extend(extra_variables)
+            
         # Generate any global variable in configuration
-        for varlist in configuration.getglobalVars():
+        for varlist, varlist_variables in varlists:
             variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local")
             # Generate variable block with modifier
             config += [("  VAR_GLOBAL", ())]
@@ -281,7 +290,7 @@
                 config += [(" NON_RETAIN", (tagname, variable_type, (var_number, var_number + len(varlist.getvariable())), "non_retain"))]
             config += [("\n", ())]
             # Generate any variable of this block
-            for var in varlist.getvariable():
+            for var in varlist_variables:
                 vartype_content = var.gettype().getcontent()
                 if vartype_content["name"] == "derived":
                     var_type = vartype_content["value"].getname()
@@ -512,15 +521,24 @@
                         current_type = var_type
                         break
             while current_type is not None and len(parts) > 0:
-                tagname = self.ParentGenerator.Controler.ComputeDataTypeName(current_type)
-                infos = self.ParentGenerator.Controler.GetDataTypeInfos(tagname)
-                name = parts.pop(0)
-                current_type = None
-                if infos is not None and infos["type"] == "Structure":
-                    for element in infos["elements"]:
-                        if element["Name"] == name:
-                            current_type = element["Type"]
+                blocktype = self.ParentGenerator.Controler.GetBlockType(current_type)
+                if blocktype is not None:
+                    name = parts.pop(0)
+                    current_type = None
+                    for var_name, var_type, var_modifier in blocktype["inputs"] + blocktype["outputs"]:
+                        if var_name == name:
+                            current_type = var_type
                             break
+                else:
+                    tagname = self.ParentGenerator.Controler.ComputeDataTypeName(current_type)
+                    infos = self.ParentGenerator.Controler.GetDataTypeInfos(tagname)
+                    if infos is not None and infos["type"] == "Structure":
+                        name = parts.pop(0)
+                        current_type = None
+                        for element in infos["elements"]:
+                            if element["Name"] == name:
+                                current_type = element["Type"]
+                                break
         return current_type
     
     # Return connectors linked by a connection to the given connector
diff -r 3c6ce0a5ab2c -r 235a9ec83b95 ProjectController.py
--- a/ProjectController.py	Thu Nov 15 22:57:55 2012 +0100
+++ b/ProjectController.py	Thu Nov 15 23:00:53 2012 +0100
@@ -503,7 +503,10 @@
                     # finally store into located variable list
                     locations.append(resdict)
         return locations
-        
+    
+    def GetConfNodeGlobalInstances(self):
+        return self._GlobalInstances()
+    
     def _Generate_SoftPLC(self):
         """
         Generate SoftPLC ST/IL/SFC code out of PLCOpenEditor controller, and compile it with IEC2C
@@ -697,15 +700,23 @@
                     self._ProgramList.append(attrs)
         
                 # second section contains all variables
+                config_FBs = {}
                 for line in ListGroup[1]:
                     # Split and Maps each field to dictionnary entries
                     attrs = dict(zip(VariablesListAttributeName,line.strip().split(';')))
                     # Truncate "C_path" to remove conf an ressources names
                     parts = attrs["C_path"].split(".",2)
                     if len(parts) > 2:
-                        attrs["C_path"] = '__'.join(parts[1:])
+                        config_FB = config_FBs.get(tuple(parts[:2]))
+                        if config_FB:
+                            parts = [config_FB] + parts[2:]
+                            attrs["C_path"] = '.'.join(parts)
+                        else: 
+                            attrs["C_path"] = '__'.join(parts[1:])
                     else:
                         attrs["C_path"] = '__'.join(parts)
+                        if attrs["vartype"] == "FB":
+                            config_FBs[tuple(parts)] = attrs["C_path"]
                     # Push this dictionnary into result.
                     self._VariablesList.append(attrs)
                     # Fill in IEC<->C translation dicts
@@ -741,18 +752,19 @@
                "IN":"extern __IEC_%(type)s_p %(C_path)s;",
                "MEM":"extern __IEC_%(type)s_p %(C_path)s;",
                "OUT":"extern __IEC_%(type)s_p %(C_path)s;",
-               "VAR":"extern __IEC_%(type)s_t %(C_path)s;"}[v["vartype"]]%v 
-               for v in self._VariablesList if v["vartype"] != "FB" and v["C_path"].find('.')<0]),
+               "VAR":"extern __IEC_%(type)s_t %(C_path)s;",
+               "FB":"extern %(type)s %(C_path)s;"}[v["vartype"]]%v 
+               for v in self._VariablesList if v["C_path"].find('.')<0]),
            "for_each_variable_do_code":"\n".join([
-               {"EXT":"    (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
-                "IN":"    (*fp)((void*)&%(C_path)s,%(type)s_P_ENUM);\n",
-                "MEM":"    (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
-                "OUT":"    (*fp)((void*)&%(C_path)s,%(type)s_O_ENUM);\n",
-                "VAR":"    (*fp)((void*)&%(C_path)s,%(type)s_ENUM);\n"}[v["vartype"]]%v
+               {"EXT":"    (*fp)((void*)&(%(C_path)s),%(type)s_P_ENUM);\n",
+                "IN":"    (*fp)((void*)&(%(C_path)s),%(type)s_P_ENUM);\n",
+                "MEM":"    (*fp)((void*)&(%(C_path)s),%(type)s_O_ENUM);\n",
+                "OUT":"    (*fp)((void*)&(%(C_path)s),%(type)s_O_ENUM);\n",
+                "VAR":"    (*fp)((void*)&(%(C_path)s),%(type)s_ENUM);\n"}[v["vartype"]]%v
                 for v in self._VariablesList if v["vartype"] != "FB" and v["type"] in DebugTypesSize ]),
            "find_variable_case_code":"\n".join([
                "    case %(num)s:\n"%v+
-               "        *varp = (void*)&%(C_path)s;\n"%v+
+               "        *varp = (void*)&(%(C_path)s);\n"%v+
                {"EXT":"        return %(type)s_P_ENUM;\n",
                 "IN":"        return %(type)s_P_ENUM;\n",
                 "MEM":"        return %(type)s_O_ENUM;\n",