43 |
43 |
44 # Dictionary for quickly translate boolean into integer value |
44 # Dictionary for quickly translate boolean into integer value |
45 BOOL_TRANSLATE = {True : "1", False : "0"} |
45 BOOL_TRANSLATE = {True : "1", False : "0"} |
46 |
46 |
47 # Dictionary for quickly translate eds access value into canfestival access value |
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"} |
48 ACCESS_TRANSLATE = {"RO" : "ro", "WO" : "wo", "RW" : "rw", "RWR" : "rw", "RWW" : "rw", "CONST" : "ro"} |
49 |
49 |
50 # Function for verifying data values |
50 # Function for verifying data values |
51 is_integer = lambda x: type(x) in (IntType, LongType) |
51 is_integer = lambda x: type(x) in (IntType, LongType) |
52 is_string = lambda x: type(x) in (StringType, UnicodeType) |
52 is_string = lambda x: type(x) in (StringType, UnicodeType) |
53 is_boolean = lambda x: x in (0, 1) |
53 is_boolean = lambda x: x in (0, 1) |
54 |
54 |
55 # Define checking of value for each attribute |
55 # Define checking of value for each attribute |
56 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, |
56 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, |
57 "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, |
57 "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, |
58 "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer, |
58 "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer, |
59 "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"], |
59 "ACCESSTYPE" : lambda x: x.upper() in ACCESS_TRANSLATE.keys(), |
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", |
152 # verify that there is no whitespace into keyname |
152 # verify that there is no whitespace into keyname |
153 if keyname.isalnum(): |
153 if keyname.isalnum(): |
154 # value can be preceded and followed by whitespaces, so we escape them |
154 # value can be preceded and followed by whitespaces, so we escape them |
155 value = value.strip() |
155 value = value.strip() |
156 |
156 |
157 # First case, value starts with "0x", then it's an hexadecimal value |
157 # First case, value starts with "0x" or "-0x", then it's an hexadecimal value |
158 if value.startswith("0x"): |
158 if value.startswith("0x") or value.startswith("-0x"): |
159 try: |
159 try: |
160 computed_value = int(value, 16) |
160 computed_value = int(value, 16) |
161 except: |
161 except: |
162 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) |
162 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) |
163 elif value.isdigit(): |
163 elif value.isdigit() or value.startswith("-") and value[1:].isdigit(): |
164 # Second case, value is a number and starts with "0", then it's an octal value |
164 # Second case, value is a number and starts with "0" or "-0", then it's an octal value |
165 if value.startswith("0"): |
165 if value.startswith("0") or value.startswith("-0"): |
166 computed_value = int(value, 8) |
166 computed_value = int(value, 8) |
167 # Third case, value is a number and don't start with "0", then it's a decimal value |
167 # Third case, value is a number and don't start with "0", then it's a decimal value |
168 else: |
168 else: |
169 computed_value = int(value) |
169 computed_value = int(value) |
170 # In any other case, we keep string value |
170 # In any other case, we keep string value |
311 test = int(value.replace("$NODEID+", ""), 16) |
311 test = int(value.replace("$NODEID+", ""), 16) |
312 computed_value = "\"%s\""%value |
312 computed_value = "\"%s\""%value |
313 except: |
313 except: |
314 raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) |
314 raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) |
315 # Second case, value starts with "0x", then it's an hexadecimal value |
315 # Second case, value starts with "0x", then it's an hexadecimal value |
316 elif value.startswith("0x"): |
316 elif value.startswith("0x") or value.startswith("-0x"): |
317 try: |
317 try: |
318 computed_value = int(value, 16) |
318 computed_value = int(value, 16) |
319 except: |
319 except: |
320 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) |
320 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) |
321 elif value.isdigit(): |
321 elif value.isdigit() or value.startswith("-") and value[1:].isdigit(): |
322 # Third case, value is a number and starts with "0", then it's an octal value |
322 # Third case, value is a number and starts with "0", then it's an octal value |
323 if value.startswith("0"): |
323 if value.startswith("0") or value.startswith("-0"): |
324 computed_value = int(value, 8) |
324 computed_value = int(value, 8) |
325 # Forth case, value is a number and don't start with "0", then it's a decimal value |
325 # Forth case, value is a number and don't start with "0", then it's a decimal value |
326 else: |
326 else: |
327 computed_value = int(value) |
327 computed_value = int(value) |
328 # In any other case, we keep string value |
328 # In any other case, we keep string value |
663 # Add mapping for entry |
663 # Add mapping for entry |
664 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1) |
664 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1) |
665 # Add mapping for first subindex |
665 # Add mapping for first subindex |
666 Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], |
666 Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], |
667 "type" : values["DATATYPE"], |
667 "type" : values["DATATYPE"], |
668 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]], |
668 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"].upper()], |
669 "pdo" : values.get("PDOMAPPING", 0) == 1}) |
669 "pdo" : values.get("PDOMAPPING", 0) == 1}) |
670 # Second case, entry is an ARRAY |
670 # Second case, entry is an ARRAY or RECORD |
671 elif values["OBJECTTYPE"] == 8: |
671 elif values["OBJECTTYPE"] in [8, 9]: |
672 # Extract maximum subindex number defined |
672 # Extract maximum subindex number defined |
673 try: |
673 try: |
674 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] |
674 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] |
675 except: |
675 except: |
676 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY entry"%entry |
676 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY entry"%entry |
682 for subindex in xrange(1, int(max_subindex) + 1): |
682 for subindex in xrange(1, int(max_subindex) + 1): |
683 # if subindex is defined |
683 # if subindex is defined |
684 if subindex in values["subindexes"]: |
684 if subindex in values["subindexes"]: |
685 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], |
685 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], |
686 "type" : values["subindexes"][subindex]["DATATYPE"], |
686 "type" : values["subindexes"][subindex]["DATATYPE"], |
687 "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]], |
687 "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"].upper()], |
688 "pdo" : values["subindexes"][subindex].get("PDOMAPPING", 0) == 1}) |
688 "pdo" : values["subindexes"][subindex].get("PDOMAPPING", 0) == 1}) |
689 # if not, we add a mapping for compatibility |
689 # if not, we add a mapping for compatibility |
690 else: |
690 else: |
691 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False}) |
691 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False}) |
692 # Third case, entry is an RECORD |
692 ## # Third case, entry is an RECORD |
693 elif values["OBJECTTYPE"] == 9: |
693 ## elif values["OBJECTTYPE"] == 9: |
694 # Verify that the first subindex is defined |
694 ## # Verify that the first subindex is defined |
695 if 0 not in values["subindexes"]: |
695 ## if 0 not in values["subindexes"]: |
696 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry |
696 ## raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry |
697 # Add mapping for entry |
697 ## # Add mapping for entry |
698 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7) |
698 ## Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7) |
699 # Add mapping for first subindex |
699 ## # Add mapping for first subindex |
700 Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False}) |
700 ## Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False}) |
701 # Verify that second subindex is defined |
701 ## # Verify that second subindex is defined |
702 if 1 in values: |
702 ## if 1 in values["subindexes"]: |
703 Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", |
703 ## Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", |
704 "type" : values["subindexes"][1]["DATATYPE"], |
704 ## "type" : values["subindexes"][1]["DATATYPE"], |
705 "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]], |
705 ## "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"].upper()], |
706 "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1}) |
706 ## "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1, |
707 else: |
707 ## "nbmax" : 0xFE}) |
708 raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry |
708 ## else: |
|
709 ## raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry |
709 |
710 |
710 # Define entry for the new node |
711 # Define entry for the new node |
711 |
712 |
712 # First case, entry is a VAR |
713 # First case, entry is a VAR |
713 if values["OBJECTTYPE"] == 7: |
714 if values["OBJECTTYPE"] == 7: |
720 Node.AddEntry(entry, 0, value) |
721 Node.AddEntry(entry, 0, value) |
721 # Second case, entry is an ARRAY or a RECORD |
722 # Second case, entry is an ARRAY or a RECORD |
722 elif values["OBJECTTYPE"] in (8, 9): |
723 elif values["OBJECTTYPE"] in (8, 9): |
723 # Verify that "Subnumber" attribute is defined and has a valid value |
724 # Verify that "Subnumber" attribute is defined and has a valid value |
724 if "SUBNUMBER" in values and values["SUBNUMBER"] > 0: |
725 if "SUBNUMBER" in values and values["SUBNUMBER"] > 0: |
|
726 consecutive = False |
725 # Extract maximum subindex number defined |
727 # Extract maximum subindex number defined |
726 try: |
728 try: |
727 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] |
729 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] |
728 except: |
730 except: |
729 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry |
731 max_subindex = values["SUBNUMBER"] - 1 |
|
732 consecutive = True |
|
733 #raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry |
730 Node.AddEntry(entry, value = []) |
734 Node.AddEntry(entry, value = []) |
731 # Define value for all subindexes except the first |
735 # Define value for all subindexes except the first |
732 for subindex in xrange(1, int(max_subindex) + 1): |
736 for subindex in xrange(1, int(max_subindex) + 1): |
733 # Take default value if it is defined and entry is defined |
737 # Take default value if it is defined and entry is defined |
734 if subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]: |
738 if subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]: |
735 value = values["subindexes"][subindex]["DEFAULTVALUE"] |
739 value = values["subindexes"][subindex]["DEFAULTVALUE"] |
736 # Find default value for value type of the subindex |
740 # Find default value for value type of the subindex |
|
741 elif subindex in values["subindexes"] or not consecutive: |
|
742 value = GetDefaultValue(entry, subindex) |
737 else: |
743 else: |
738 value = GetDefaultValue(entry, subindex) |
744 raise SyntaxError, "Error on entry 0x%4.4X:\nCan't recompose implemented subindexes in this ARRAY or RECORD entry"%entry |
739 Node.AddEntry(entry, subindex, value) |
745 Node.AddEntry(entry, subindex, value) |
740 else: |
746 else: |
741 raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry |
747 raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry |
742 return Node |
748 return Node |
743 except SyntaxError, message: |
749 except SyntaxError, message: |