objdictgen/eds_utils.py
changeset 205 dac0f9b4e3f8
parent 182 988f2b302aa6
child 206 6787754b251b
equal deleted inserted replaced
204:44ce74232ccb 205:dac0f9b4e3f8
    21 #License along with this library; if not, write to the Free Software
    21 #License along with this library; if not, write to the Free Software
    22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 
    23 
    24 
    24 
    25 import node
    25 import node
       
    26 from node import nosub, var, array, rec, plurivar, pluriarray, plurirec
    26 from sets import *
    27 from sets import *
    27 from types import *
    28 from types import *
    28 from time import *
    29 from time import *
    29 import os,re
    30 import os,re
    30 
    31 
    31 # Regular expression for finding index section names
    32 # Regular expression for finding index section names
    32 index_model = re.compile('([0-9a-fA-F]{1,4})')
    33 index_model = re.compile('([0-9A-F]{1,4})')
    33 # Regular expression for finding subindex section names
    34 # Regular expression for finding subindex section names
    34 subindex_model = re.compile('([0-9a-fA-F]{1,4})sub([0-9a-fA-F]{1,2})')
    35 subindex_model = re.compile('([0-9A-F]{1,4})SUB([0-9A-F]{1,2})')
       
    36 
       
    37 # Regular expression for finding NodeXPresent keynames
       
    38 nodepresent_model = re.compile('NODE([0-9]{1,3})PRESENT')
       
    39 # Regular expression for finding NodeXName keynames
       
    40 nodename_model = re.compile('NODE([0-9]{1,3})NAME')
       
    41 # Regular expression for finding NodeXDCFName keynames
       
    42 nodedcfname_model = re.compile('NODE([0-9]{1,3})DCFNAME')
    35 
    43 
    36 # Dictionary for quickly translate boolean into integer value
    44 # Dictionary for quickly translate boolean into integer value
    37 BOOL_TRANSLATE = {True : "1", False : "0"}
    45 BOOL_TRANSLATE = {True : "1", False : "0"}
       
    46 
       
    47 # Dictionary for quickly translate eds access value into canfestival access value
       
    48 ACCESS_TRANSLATE = {"ro" : "ro", "wo" : "wo", "rw" : "rw", "rwr" : "rw", "rww" : "rw", "const" : "ro"}
    38 
    49 
    39 # Function for verifying data values
    50 # Function for verifying data values
    40 is_integer = lambda x: type(x) == IntType
    51 is_integer = lambda x: type(x) == IntType
    41 is_string = lambda x: type(x) == StringType
    52 is_string = lambda x: type(x) == StringType
       
    53 is_boolean = lambda x: x in (0, 1)
    42 
    54 
    43 # Define checking of value for each attribute
    55 # Define checking of value for each attribute
    44 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, 
    56 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, 
    45                     "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, 
    57                     "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, 
    46                     "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer,
    58                     "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer,
    47                     "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"],
    59                     "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"],
    48                     "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : lambda x: x in (0, 1),
    60                     "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : is_boolean,
    49                     "OBJFLAGS" : is_integer}
    61                     "OBJFLAGS" : is_integer}
    50 
    62 
    51 # Define entry parameters by entry ObjectType number
    63 # Define entry parameters by entry ObjectType number
    52 ENTRY_TYPES = {7 : {"name" : " VAR",
    64 ENTRY_TYPES = {7 : {"name" : " VAR",
    53                     "require" : ["PARAMETERNAME", "OBJECTTYPE", "DATATYPE", "ACCESSTYPE", "PDOMAPPING"],
    65                     "require" : ["PARAMETERNAME", "OBJECTTYPE", "DATATYPE", "ACCESSTYPE", "PDOMAPPING"],
    61 
    73 
    62 
    74 
    63 # Function that search into Node Mappings the informations about an index or a subindex
    75 # Function that search into Node Mappings the informations about an index or a subindex
    64 # and return the default value
    76 # and return the default value
    65 def GetDefaultValue(index, subIndex = None):
    77 def GetDefaultValue(index, subIndex = None):
    66     infos = Manager.GetEntryInfos(index, Node)
    78     infos = Node.GetEntryInfos(index)
    67     if infos["struct"] & node.OD_MultipleSubindexes:
    79     if infos["struct"] & node.OD_MultipleSubindexes:
    68         # First case entry is a record
    80         # First case entry is a record
    69         if infos["struct"] & node.OD_IdenticalSubindexes:
    81         if infos["struct"] & node.OD_IdenticalSubindexes:
    70             subentry_infos = Manager.GetSubentryInfos(index, 1, Node)
    82             subentry_infos = Node.GetSubentryInfos(index, 1)
    71         # Second case entry is an array
    83         # Second case entry is an array
    72         else:
    84         else:
    73             subentry_infos = Manager.GetSubentryInfos(index, subIndex, Node)
    85             subentry_infos = Node.GetSubentryInfos(index, subIndex)
    74         # If a default value is defined for this subindex, returns it
    86         # If a default value is defined for this subindex, returns it
    75         if "default" in subentry_infos:
    87         if "default" in subentry_infos:
    76             return subentry_infos["default"]
    88             return subentry_infos["default"]
    77         # If not, returns the default value for the subindex type
    89         # If not, returns the default value for the subindex type
    78         else:
    90         else:
    79             return Manager.GetTypeDefaultValue(subentry_infos["type"], Node)
    91             return Node.GetTypeDefaultValue(subentry_infos["type"])
    80     # Third case entry is a var
    92     # Third case entry is a var
    81     else:
    93     else:
    82         subentry_infos = Manager.GetSubentryInfos(index, 0, Node)
    94         subentry_infos = Node.GetSubentryInfos(index, 0)
    83         # If a default value is defined for this subindex, returns it
    95         # If a default value is defined for this subindex, returns it
    84         if "default" in subentry_infos:
    96         if "default" in subentry_infos:
    85             return subentry_infos["default"]
    97             return subentry_infos["default"]
    86         # If not, returns the default value for the subindex type
    98         # If not, returns the default value for the subindex type
    87         else:
    99         else:
    88             return Manager.GetTypeDefaultValue(subentry_infos["type"], Node)
   100             return Node.GetTypeDefaultValue(subentry_infos["type"])
    89     return None
   101     return None
    90 
   102 
    91 
   103 
    92 #-------------------------------------------------------------------------------
   104 #-------------------------------------------------------------------------------
    93 #                               Parse file
   105 #                               Parse file
    98 # an EDS file
   110 # an EDS file
    99 SECTION_KEYNAMES = ["FILEINFO", "DEVICEINFO", "DUMMYUSAGE", "COMMENTS", 
   111 SECTION_KEYNAMES = ["FILEINFO", "DEVICEINFO", "DUMMYUSAGE", "COMMENTS", 
   100                     "MANDATORYOBJECTS", "OPTIONALOBJECTS", "MANUFACTUREROBJECTS"]
   112                     "MANDATORYOBJECTS", "OPTIONALOBJECTS", "MANUFACTUREROBJECTS"]
   101 
   113 
   102 
   114 
       
   115 # Function that extract sections from a file and returns a dictionary of the informations
       
   116 def ExtractSections(file):
       
   117     return [(blocktuple[0],                # EntryName : Assignements dict
       
   118              blocktuple[-1].splitlines())  # all the lines
       
   119              for blocktuple in [           # Split the eds files into
       
   120              block.split("]")              # (EntryName,Assignements) tuple
       
   121              for block in                  # for each blocks staring with '['
       
   122              file.split("[")]
       
   123              if blocktuple[0].isalnum()]   # if EntryName exists
       
   124     
       
   125 
       
   126 # Function that parse an CPJ file and returns a dictionary of the informations
       
   127 def ParseCPJFile(filepath):
       
   128     networks = []
       
   129     # Read file text
       
   130     cpj_file = open(filepath,'r').read()
       
   131     sections = ExtractSections(cpj_file)
       
   132     # Parse assignments for each section
       
   133     for section_name, assignments in sections:
       
   134         
       
   135         # Verify that section name is TOPOLOGY 
       
   136         if section_name.upper() in "TOPOLOGY":
       
   137             
       
   138             # Reset values for topology
       
   139             topology = {"Name" : "", "Nodes" : {}}
       
   140             
       
   141             for assignment in assignments:
       
   142                 # Escape any comment
       
   143                 if assignment.startswith(";"):
       
   144                     pass
       
   145                 # Verify that line is a valid assignment
       
   146                 elif assignment.find('=') > 0:
       
   147                     # Split assignment into the two values keyname and value
       
   148                     # Verify that there is only one '=' character in the line
       
   149                     try:
       
   150                         keyname, value = assignment.split("=")
       
   151                     except:
       
   152                         raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip()
       
   153                     
       
   154                     # keyname must be immediately followed by the "=" sign, so we
       
   155                     # verify that there is no whitespace into keyname
       
   156                     if keyname.isalnum():
       
   157                         # value can be preceded and followed by whitespaces, so we escape them
       
   158                         value = value.strip()
       
   159                 
       
   160                         # First case, value starts with "0x", then it's an hexadecimal value
       
   161                         if value.startswith("0x"):
       
   162                             try:
       
   163                                 computed_value = int(value, 16)
       
   164                             except:
       
   165                                 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   166                         elif value.isdigit():
       
   167                             # Second case, value is a number and starts with "0", then it's an octal value
       
   168                             if value.startswith("0"):
       
   169                                 computed_value = int(value, 8)
       
   170                             # Third case, value is a number and don't start with "0", then it's a decimal value
       
   171                             else:
       
   172                                 computed_value = int(value)
       
   173                         # In any other case, we keep string value
       
   174                         else:
       
   175                             computed_value = value
       
   176                         
       
   177                         # Search if the section name match any cpj expression
       
   178                         nodepresent_result = nodepresent_model.match(keyname.upper())
       
   179                         nodename_result = nodename_model.match(keyname.upper())
       
   180                         nodedcfname_result = nodedcfname_model.match(keyname.upper())
       
   181                         
       
   182                         if keyname.upper() == "NETNAME":
       
   183                             if not is_string(computed_value):
       
   184                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   185                             topology["Name"] = computed_value
       
   186                         elif keyname.upper() == "NODES":
       
   187                             if not is_integer(computed_value):
       
   188                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   189                             topology["Number"] = computed_value
       
   190                         elif keyname.upper() == "EDSBASENAME":
       
   191                             if not is_string(computed_value):
       
   192                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   193                             topology["Path"] = computed_value
       
   194                         elif nodepresent_result:
       
   195                             if not is_boolean(computed_value):
       
   196                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   197                             nodeid = int(nodepresent_result.groups()[0])
       
   198                             if nodeid not in topology["Nodes"].keys():
       
   199                                 topology["Nodes"][nodeid] = {}
       
   200                             topology["Nodes"][nodeid]["Present"] = computed_value
       
   201                         elif nodename_result:
       
   202                             if not is_string(value):
       
   203                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   204                             nodeid = int(nodename_result.groups()[0])
       
   205                             if nodeid not in topology["Nodes"].keys():
       
   206                                 topology["Nodes"][nodeid] = {}
       
   207                             topology["Nodes"][nodeid]["Name"] = computed_value
       
   208                         elif nodedcfname_result:
       
   209                             if not is_string(computed_value):
       
   210                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   211                             nodeid = int(nodedcfname_result.groups()[0])
       
   212                             if nodeid not in topology["Nodes"].keys():
       
   213                                 topology["Nodes"][nodeid] = {}
       
   214                             topology["Nodes"][nodeid]["DCFName"] = computed_value
       
   215                         else:
       
   216                             raise SyntaxError, "Keyname \"%s\" not recognised for section \"[%s]\""%(keyname, section_name)
       
   217                         
       
   218                 # All lines that are not empty and are neither a comment neither not a valid assignment
       
   219                 elif assignment.strip() != "":
       
   220                     raise SyntaxError, "\"%s\" is not a valid CPJ line"%assignment.strip()
       
   221         
       
   222             if "Number" not in topology.keys():
       
   223                 raise SyntaxError, "\"Nodes\" keyname in \"[%s]\" section is missing"%section_name
       
   224         
       
   225             if topology["Number"] != len(topology["Nodes"]):
       
   226                 raise SyntaxError, "\"Nodes\" value not corresponding to number of nodes defined"
       
   227             
       
   228             for nodeid, node in topology["Nodes"].items():
       
   229                 if "Present" not in node.keys():
       
   230                     raise SyntaxError, "\"Node%dPresent\" keyname in \"[%s]\" section is missing"%(nodeid, section_name)
       
   231             
       
   232             networks.append(topology)
       
   233             
       
   234         # In other case, there is a syntax problem into CPJ file
       
   235         else:
       
   236             raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name
       
   237     
       
   238     return networks
       
   239 
   103 # Function that parse an EDS file and returns a dictionary of the informations
   240 # Function that parse an EDS file and returns a dictionary of the informations
   104 def ParseFile(filepath):
   241 def ParseEDSFile(filepath):
   105     eds_dict = {}
   242     eds_dict = {}
   106     # Read file text
   243     # Read file text
   107     eds_file = open(filepath,'r').read()
   244     eds_file = open(filepath,'r').read()
   108     sections = [(blocktuple[0],                # EntryName : Assignements dict
   245     sections = ExtractSections(eds_file)
   109                  blocktuple[-1].splitlines())  # all the lines
       
   110                  for blocktuple in [           # Split the eds files into
       
   111                  block.split("]")              # (EntryName,Assignements) tuple
       
   112                  for block in                  # for each blocks staring with '['
       
   113                  eds_file.split("[")]
       
   114                  if blocktuple[0].isalnum()]   # if EntryName exists
       
   115     
   246     
   116     # Parse assignments for each section
   247     # Parse assignments for each section
   117     for section_name, assignments in sections:
   248     for section_name, assignments in sections:
   118         # Reset values of entry
   249         # Reset values of entry
   119         values = {}
   250         values = {}
   120         
   251         
   121         # Search if the section name match an index or subindex expression
   252         # Search if the section name match an index or subindex expression
   122         index_result = index_model.match(section_name)
   253         index_result = index_model.match(section_name.upper())
   123         subindex_result = subindex_model.match(section_name)
   254         subindex_result = subindex_model.match(section_name.upper())
   124         
   255         
   125         # Compilation of the EDS information dictionary
   256         # Compilation of the EDS information dictionary
   126         
   257         
   127         is_entry = False
   258         is_entry = False
   128         # First case, section name is in SECTION_KEYNAMES 
   259         # First case, section name is in SECTION_KEYNAMES 
   168             if assignment.startswith(";"):
   299             if assignment.startswith(";"):
   169                 pass
   300                 pass
   170             # Verify that line is a valid assignment
   301             # Verify that line is a valid assignment
   171             elif assignment.find('=') > 0:
   302             elif assignment.find('=') > 0:
   172                 # Split assignment into the two values keyname and value
   303                 # Split assignment into the two values keyname and value
       
   304                 # Verify that there is only one '=' character in the line
   173                 try:
   305                 try:
   174                     keyname, value = assignment.split("=")
   306                     keyname, value = assignment.split("=")
   175                 except:
   307                 except:
   176                     raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip()
   308                     raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip()
   177                 # keyname must be immediately followed by the "=" sign, so we
   309                 # keyname must be immediately followed by the "=" sign, so we
   180                     # value can be preceded and followed by whitespaces, so we escape them
   312                     # value can be preceded and followed by whitespaces, so we escape them
   181                     value = value.strip()
   313                     value = value.strip()
   182                     # First case, value starts with "$NODEID", then it's a formula
   314                     # First case, value starts with "$NODEID", then it's a formula
   183                     if value.startswith("$NODEID"):
   315                     if value.startswith("$NODEID"):
   184                         try:
   316                         try:
   185                             computed_value = int(value.replace("$NODEID+", ""), 16)
   317                             test = int(value.replace("$NODEID+", ""), 16)
       
   318                             computed_value = value.replace("$NODEID", "self.ID")
   186                         except:
   319                         except:
   187                             raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
   320                             raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
   188                     # Second case, value starts with "0x", then it's an hexadecimal value
   321                     # Second case, value starts with "0x", then it's an hexadecimal value
   189                     elif value.startswith("0x"):
   322                     elif value.startswith("0x"):
   190                         try:
   323                         try:
   318     fileContent += "DynamicChannelsSupported=0\n"
   451     fileContent += "DynamicChannelsSupported=0\n"
   319     fileContent += "CompactPDO=0\n"
   452     fileContent += "CompactPDO=0\n"
   320     fileContent += "GroupMessaging=0\n"
   453     fileContent += "GroupMessaging=0\n"
   321     # Calculate receive and tranmit PDO numbers with the entry available
   454     # Calculate receive and tranmit PDO numbers with the entry available
   322     fileContent += "NrOfRXPDO=%d\n"%len([idx for idx in entries if 0x1400 <= idx <= 0x15FF])
   455     fileContent += "NrOfRXPDO=%d\n"%len([idx for idx in entries if 0x1400 <= idx <= 0x15FF])
   323     fileContent += "NrOfTXPDO=%d\n"%len([idx for idx in entries if 0x1400 <= idx <= 0x15FF])
   456     fileContent += "NrOfTXPDO=%d\n"%len([idx for idx in entries if 0x1800 <= idx <= 0x19FF])
   324     # LSS not supported as soon as DS-302 was not fully implemented
   457     # LSS not supported as soon as DS-302 was not fully implemented
   325     fileContent += "LSS_Supported=0\n"
   458     fileContent += "LSS_Supported=0\n"
   326     
   459     
   327     # Generate Dummy Usage section
   460     # Generate Dummy Usage section
   328     fileContent += "\n[DummyUsage]\n"
   461     fileContent += "\n[DummyUsage]\n"
   453         WriteFile(filepath, content)
   586         WriteFile(filepath, content)
   454         return None
   587         return None
   455     except ValueError, message:
   588     except ValueError, message:
   456         return "Unable to generate EDS file\n%s"%message
   589         return "Unable to generate EDS file\n%s"%message
   457     
   590     
       
   591 # Function that generate the CPJ file content for the nodelist
       
   592 def GenerateCPJContent(nodelist):
       
   593     nodes = nodelist.SlaveNodes.keys()
       
   594     nodes.sort()
       
   595     
       
   596     fileContent = "[TOPOLOGY]\n"
       
   597     fileContent += "NetName=%s\n"%nodelist.GetNetworkName()
       
   598     fileContent += "Nodes=0x%2.2X\n"%len(nodes)
       
   599     
       
   600     for nodeid in nodes:
       
   601         fileContent += "Node%dPresent=0x01\n"%nodeid
       
   602         fileContent += "Node%dName=%s\n"%(nodeid, nodelist.SlaveNodes[nodeid]["Name"])
       
   603         fileContent += "Node%dDCFName=%s\n"%(nodeid, nodelist.SlaveNodes[nodeid]["EDS"])
       
   604         
       
   605     fileContent += "EDSBaseName=eds\n"
       
   606     return fileContent
   458 
   607 
   459 # Function that generates Node from an EDS file
   608 # Function that generates Node from an EDS file
   460 def GenerateNode(filepath, manager, cwd):
   609 def GenerateNode(filepath, cwd, nodeID = 0):
   461     global Node
   610     global Node
   462     global Manager
       
   463     Manager = manager
       
   464     # Create a new node
   611     # Create a new node
   465     Node = node.Node()
   612     Node = node.Node(id = nodeID)
   466     try:
   613     try:
   467         # Parse file and extract dictionary of EDS entry
   614         # Parse file and extract dictionary of EDS entry
   468         eds_dict = ParseFile(filepath)
   615         eds_dict = ParseEDSFile(filepath)
   469         # Extract Profile Number from Device Type entry
   616         # Extract Profile Number from Device Type entry
   470         ProfileNb = eds_dict[0x1000]["DEFAULTVALUE"] & 0x0000ffff
   617         ProfileNb = eds_dict[0x1000]["DEFAULTVALUE"] & 0x0000ffff
   471         # If profile is not DS-301 or DS-302
   618         # If profile is not DS-301 or DS-302
   472         if ProfileNb not in [301, 302]:
   619         if ProfileNb not in [301, 302]:
   473             # Compile Profile name and path to .prf file
   620             # Compile Profile name and path to .prf file
   488             # All sections with a name in keynames are escaped
   635             # All sections with a name in keynames are escaped
   489             if entry in SECTION_KEYNAMES:
   636             if entry in SECTION_KEYNAMES:
   490                 pass
   637                 pass
   491             else:
   638             else:
   492                 # Extract informations for the entry
   639                 # Extract informations for the entry
   493                 entry_infos = Manager.GetEntryInfos(entry, Node)
   640                 entry_infos = Node.GetEntryInfos(entry)
   494                 
   641                 
   495                 # If no informations are available, then we write them
   642                 # If no informations are available, then we write them
   496                 if not entry_infos:
   643                 if not entry_infos:
   497                     # First case, entry is a VAR
   644                     # First case, entry is a VAR
   498                     if values["OBJECTTYPE"] == 7:
   645                     if values["OBJECTTYPE"] == 7:
   499                         # Add mapping for entry
   646                         # Add mapping for entry
   500                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1)
   647                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1)
   501                         # Add mapping for first subindex
   648                         # Add mapping for first subindex
   502                         Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], 
   649                         Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], 
   503                                                                  "type" : values["DATATYPE"], 
   650                                                                  "type" : values["DATATYPE"], 
   504                                                                  "access" : values["ACCESSTYPE"], 
   651                                                                  "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]], 
   505                                                                  "pdo" : values["PDOMAPPING"] == 1})
   652                                                                  "pdo" : values["PDOMAPPING"] == 1})
   506                     # Second case, entry is an ARRAY
   653                     # Second case, entry is an ARRAY
   507                     elif values["OBJECTTYPE"] == 8:
   654                     elif values["OBJECTTYPE"] == 8:
   508                         # Extract maximum subindex number defined
   655                         # Extract maximum subindex number defined
   509                         try:
   656                         try:
   518                         for subindex in xrange(1, int(max_subindex) + 1):
   665                         for subindex in xrange(1, int(max_subindex) + 1):
   519                             # if subindex is defined
   666                             # if subindex is defined
   520                             if subindex in values["subindexes"]:
   667                             if subindex in values["subindexes"]:
   521                                 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], 
   668                                 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], 
   522                                                                                 "type" : values["subindexes"][subindex]["DATATYPE"], 
   669                                                                                 "type" : values["subindexes"][subindex]["DATATYPE"], 
   523                                                                                 "access" : values["subindexes"][subindex]["ACCESSTYPE"], 
   670                                                                                 "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]], 
   524                                                                                 "pdo" : values["subindexes"][subindex]["PDOMAPPING"] == 1})
   671                                                                                 "pdo" : values["subindexes"][subindex]["PDOMAPPING"] == 1})
   525                             # if not, we add a mapping for compatibility 
   672                             # if not, we add a mapping for compatibility 
   526                             else:
   673                             else:
   527                                 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False})
   674                                 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False})
   528                     # Third case, entry is an RECORD
   675                     # Third case, entry is an RECORD
   536                         Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
   683                         Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
   537                         # Verify that second subindex is defined
   684                         # Verify that second subindex is defined
   538                         if 1 in values:
   685                         if 1 in values:
   539                             Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", 
   686                             Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", 
   540                                                                      "type" : values["subindexes"][1]["DATATYPE"], 
   687                                                                      "type" : values["subindexes"][1]["DATATYPE"], 
   541                                                                      "access" : values["subindexes"][1]["ACCESSTYPE"], 
   688                                                                      "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]], 
   542                                                                      "pdo" : values["subindexes"][1]["PDOMAPPING"] == 1})
   689                                                                      "pdo" : values["subindexes"][1]["PDOMAPPING"] == 1})
   543                         else:
   690                         else:
   544                             raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
   691                             raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
   545                 
   692                 
   546                 # Define entry for the new node
   693                 # Define entry for the new node
   574                             Node.AddEntry(entry, subindex, value)
   721                             Node.AddEntry(entry, subindex, value)
   575                     else:
   722                     else:
   576                         raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry
   723                         raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry
   577         return Node
   724         return Node
   578     except SyntaxError, message:
   725     except SyntaxError, message:
   579         return "Unable to import EDS File\n%s"%message
   726         return "Unable to import EDS file\n%s"%message
   580 
   727 
   581 #-------------------------------------------------------------------------------
   728 #-------------------------------------------------------------------------------
   582 #                             Main Function
   729 #                             Main Function
   583 #-------------------------------------------------------------------------------
   730 #-------------------------------------------------------------------------------
   584 
   731 
   585 if __name__ == '__main__':
   732 if __name__ == '__main__':
   586     print ParseFile("examples/PEAK MicroMod.eds")
   733     print ParseEDSFile("examples/PEAK MicroMod.eds")
   587 
   734