60 "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : is_boolean, |
60 "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : is_boolean, |
61 "OBJFLAGS" : is_integer} |
61 "OBJFLAGS" : is_integer} |
62 |
62 |
63 # Define entry parameters by entry ObjectType number |
63 # Define entry parameters by entry ObjectType number |
64 ENTRY_TYPES = {7 : {"name" : " VAR", |
64 ENTRY_TYPES = {7 : {"name" : " VAR", |
65 "require" : ["PARAMETERNAME", "OBJECTTYPE", "DATATYPE", "ACCESSTYPE", "PDOMAPPING"], |
65 "require" : ["PARAMETERNAME", "DATATYPE", "ACCESSTYPE"], |
66 "optional" : ["LOWLIMIT", "HIGHLIMIT", "DEFAULTVALUE", "OBJFLAGS"]}, |
66 "optional" : ["OBJECTTYPE", "DEFAULTVALUE", "PDOMAPPING", "LOWLIMIT", "HIGHLIMIT", "OBJFLAGS"]}, |
67 8 : {"name" : "n ARRAY", |
67 8 : {"name" : "n ARRAY", |
68 "require" : ["SUBNUMBER", "PARAMETERNAME", "OBJECTTYPE"], |
68 "require" : ["PARAMETERNAME", "OBJECTTYPE", "SUBNUMBER"], |
69 "optional" : ["OBJFLAGS"]}, |
69 "optional" : ["OBJFLAGS"]}, |
70 9 : {"name" : " RECORD", |
70 9 : {"name" : " RECORD", |
71 "require" : ["SUBNUMBER", "PARAMETERNAME", "OBJECTTYPE"], |
71 "require" : ["PARAMETERNAME", "OBJECTTYPE", "SUBNUMBER"], |
72 "optional" : ["OBJFLAGS"]}} |
72 "optional" : ["OBJFLAGS"]}} |
73 |
73 |
74 |
74 |
75 # 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 |
76 # and return the default value |
76 # and return the default value |
115 # Function that extract sections from a file and returns a dictionary of the informations |
115 # Function that extract sections from a file and returns a dictionary of the informations |
116 def ExtractSections(file): |
116 def ExtractSections(file): |
117 return [(blocktuple[0], # EntryName : Assignements dict |
117 return [(blocktuple[0], # EntryName : Assignements dict |
118 blocktuple[-1].splitlines()) # all the lines |
118 blocktuple[-1].splitlines()) # all the lines |
119 for blocktuple in [ # Split the eds files into |
119 for blocktuple in [ # Split the eds files into |
120 block.split("]") # (EntryName,Assignements) tuple |
120 block.split("]", 1) # (EntryName,Assignements) tuple |
121 for block in # for each blocks staring with '[' |
121 for block in # for each blocks staring with '[' |
122 file.split("[")] |
122 ("\n"+file).split("\n[")] |
123 if blocktuple[0].isalnum()] # if EntryName exists |
123 if blocktuple[0].isalnum()] # if EntryName exists |
124 |
124 |
125 |
125 |
126 # Function that parse an CPJ file and returns a dictionary of the informations |
126 # Function that parse an CPJ file and returns a dictionary of the informations |
127 def ParseCPJFile(filepath): |
127 def ParseCPJFile(filepath): |
143 if assignment.startswith(";"): |
143 if assignment.startswith(";"): |
144 pass |
144 pass |
145 # Verify that line is a valid assignment |
145 # Verify that line is a valid assignment |
146 elif assignment.find('=') > 0: |
146 elif assignment.find('=') > 0: |
147 # Split assignment into the two values keyname and value |
147 # Split assignment into the two values keyname and value |
148 # Verify that there is only one '=' character in the line |
148 keyname, value = assignment.split("=", 1) |
149 try: |
|
150 keyname, value = assignment.split("=") |
|
151 except: |
|
152 raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip() |
|
153 |
149 |
154 # keyname must be immediately followed by the "=" sign, so we |
150 # keyname must be immediately followed by the "=" sign, so we |
155 # verify that there is no whitespace into keyname |
151 # verify that there is no whitespace into keyname |
156 if keyname.isalnum(): |
152 if keyname.isalnum(): |
157 # value can be preceded and followed by whitespaces, so we escape them |
153 # value can be preceded and followed by whitespaces, so we escape them |
299 if assignment.startswith(";"): |
295 if assignment.startswith(";"): |
300 pass |
296 pass |
301 # Verify that line is a valid assignment |
297 # Verify that line is a valid assignment |
302 elif assignment.find('=') > 0: |
298 elif assignment.find('=') > 0: |
303 # Split assignment into the two values keyname and value |
299 # Split assignment into the two values keyname and value |
304 # Verify that there is only one '=' character in the line |
300 keyname, value = assignment.split("=", 1) |
305 try: |
301 |
306 keyname, value = assignment.split("=") |
|
307 except: |
|
308 raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip() |
|
309 # keyname must be immediately followed by the "=" sign, so we |
302 # keyname must be immediately followed by the "=" sign, so we |
310 # verify that there is no whitespace into keyname |
303 # verify that there is no whitespace into keyname |
311 if keyname.isalnum(): |
304 if keyname.isalnum(): |
312 # value can be preceded and followed by whitespaces, so we escape them |
305 # value can be preceded and followed by whitespaces, so we escape them |
313 value = value.strip() |
306 value = value.strip() |
357 if is_entry: |
350 if is_entry: |
358 # Verify that entry has an ObjectType |
351 # Verify that entry has an ObjectType |
359 if "OBJECTTYPE" in values.keys(): |
352 if "OBJECTTYPE" in values.keys(): |
360 # Extract entry ObjectType |
353 # Extract entry ObjectType |
361 objecttype = values["OBJECTTYPE"] |
354 objecttype = values["OBJECTTYPE"] |
362 # Extract parameters defined |
|
363 keys = Set(values.keys()) |
|
364 keys.discard("subindexes") |
|
365 # Extract possible parameters and parameters required |
|
366 possible = Set(ENTRY_TYPES[objecttype]["require"] + ENTRY_TYPES[objecttype]["optional"]) |
|
367 required = Set(ENTRY_TYPES[objecttype]["require"]) |
|
368 # Verify that parameters defined contains all the parameters required |
|
369 if not keys.issuperset(required): |
|
370 missing = required.difference(keys)._data.keys() |
|
371 if len(missing) > 1: |
|
372 attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in missing]) |
|
373 else: |
|
374 attributes = "Attribute \"%s\" is"%missing[0] |
|
375 raise SyntaxError, "Error on section \"[%s]\":\n%s required for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"]) |
|
376 # Verify that parameters defined are all in the possible parameters |
|
377 if not keys.issubset(possible): |
|
378 unsupported = keys.difference(possible)._data.keys() |
|
379 if len(unsupported) > 1: |
|
380 attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in unsupported]) |
|
381 else: |
|
382 attributes = "Attribute \"%s\" is"%unsupported[0] |
|
383 raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"]) |
|
384 else: |
355 else: |
385 raise SyntaxError, "Error on section \"[%s]\":\nAttribute OBJECTTYPE is required"%section_name |
356 # Set ObjectType to VAR by default |
|
357 objecttype = 7 |
|
358 # Extract parameters defined |
|
359 keys = Set(values.keys()) |
|
360 keys.discard("subindexes") |
|
361 # Extract possible parameters and parameters required |
|
362 possible = Set(ENTRY_TYPES[objecttype]["require"] + ENTRY_TYPES[objecttype]["optional"]) |
|
363 required = Set(ENTRY_TYPES[objecttype]["require"]) |
|
364 # Verify that parameters defined contains all the parameters required |
|
365 if not keys.issuperset(required): |
|
366 missing = required.difference(keys)._data.keys() |
|
367 if len(missing) > 1: |
|
368 attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in missing]) |
|
369 else: |
|
370 attributes = "Attribute \"%s\" is"%missing[0] |
|
371 raise SyntaxError, "Error on section \"[%s]\":\n%s required for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"]) |
|
372 # Verify that parameters defined are all in the possible parameters |
|
373 if not keys.issubset(possible): |
|
374 unsupported = keys.difference(possible)._data.keys() |
|
375 if len(unsupported) > 1: |
|
376 attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in unsupported]) |
|
377 else: |
|
378 attributes = "Attribute \"%s\" is"%unsupported[0] |
|
379 raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"]) |
386 |
380 |
387 return eds_dict |
381 return eds_dict |
388 |
382 |
389 |
383 |
390 # Function that write an EDS file after generate it's content |
384 # Function that write an EDS file after generate it's content |
647 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1) |
641 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1) |
648 # Add mapping for first subindex |
642 # Add mapping for first subindex |
649 Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], |
643 Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], |
650 "type" : values["DATATYPE"], |
644 "type" : values["DATATYPE"], |
651 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]], |
645 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]], |
652 "pdo" : values["PDOMAPPING"] == 1}) |
646 "pdo" : values.get("PDOMAPPING", 0) == 1}) |
653 # Second case, entry is an ARRAY |
647 # Second case, entry is an ARRAY |
654 elif values["OBJECTTYPE"] == 8: |
648 elif values["OBJECTTYPE"] == 8: |
655 # Extract maximum subindex number defined |
649 # Extract maximum subindex number defined |
656 try: |
650 try: |
657 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] |
651 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] |
666 # if subindex is defined |
660 # if subindex is defined |
667 if subindex in values["subindexes"]: |
661 if subindex in values["subindexes"]: |
668 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], |
662 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], |
669 "type" : values["subindexes"][subindex]["DATATYPE"], |
663 "type" : values["subindexes"][subindex]["DATATYPE"], |
670 "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]], |
664 "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]], |
671 "pdo" : values["subindexes"][subindex]["PDOMAPPING"] == 1}) |
665 "pdo" : values["subindexes"][subindex].get("PDOMAPPING", 0) == 1}) |
672 # if not, we add a mapping for compatibility |
666 # if not, we add a mapping for compatibility |
673 else: |
667 else: |
674 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False}) |
668 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False}) |
675 # Third case, entry is an RECORD |
669 # Third case, entry is an RECORD |
676 elif values["OBJECTTYPE"] == 9: |
670 elif values["OBJECTTYPE"] == 9: |
684 # Verify that second subindex is defined |
678 # Verify that second subindex is defined |
685 if 1 in values: |
679 if 1 in values: |
686 Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", |
680 Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", |
687 "type" : values["subindexes"][1]["DATATYPE"], |
681 "type" : values["subindexes"][1]["DATATYPE"], |
688 "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]], |
682 "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]], |
689 "pdo" : values["subindexes"][1]["PDOMAPPING"] == 1}) |
683 "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1}) |
690 else: |
684 else: |
691 raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry |
685 raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry |
692 |
686 |
693 # Define entry for the new node |
687 # Define entry for the new node |
694 |
688 |