Keun young Park | 7339375 | 2020-09-25 17:44:43 -0700 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | |
| 3 | # Copyright (C) 2021 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | """Tools to translate VehicleProperty from types.hal into AIDL format. |
| 18 | To store it to a file: |
| 19 | $ python translate_vehicle_props.py types.hal > VehicleProperty.aidl |
| 20 | """ |
| 21 | import re |
| 22 | import sys |
| 23 | |
| 24 | ENUM_TYPE_TO_PARSE = [ "VehiclePropertyType", "VehiclePropertyGroup", "VehicleArea" ] |
| 25 | VEHICLE_PROP_ENUM = "VehicleProperty" |
| 26 | |
| 27 | RE_COMMENT_BEGIN = re.compile("\s*\/\*\*") |
| 28 | RE_COMMENT_END = re.compile("\s*\*\/") |
| 29 | RE_COMMENT_SINGLE_LINE = re.compile("\s*\/\*\*.*\*\/") |
| 30 | |
| 31 | RE_ENUM_START = re.compile("\s*enum\s*(\w+)\s?.*\{") |
| 32 | RE_ENUM_END = re.compile("\s*\}\;") |
| 33 | |
| 34 | RE_ENUM_ELEMENT = re.compile("\s*(\w+)\s*\=\s*(\w+),") |
| 35 | |
| 36 | RE_VEHICLE_PROP_ELEMENT = re.compile("\s*(\w+)\s*\=\s*\(?\s*(\w+)\s*\|?\s*(\w+\:\w+)?\s*\|?\s*(\w+:\w+)?\s*\|?\s*(\w+:\w+)?\s*\)?,") |
| 37 | |
| 38 | DBG_COMMENT = False |
| 39 | DBG_ENUM = False |
| 40 | |
| 41 | class HIDLParser: |
| 42 | def __init__(self): |
| 43 | self.inEnum = False |
| 44 | self.currentEnumName = None |
| 45 | self.inVehicleProperty = False |
| 46 | self.inComment = False |
| 47 | self.recentComments = [] |
| 48 | self.currentType = None |
| 49 | self.enumMap = {} |
| 50 | self.outputMsg = [] |
| 51 | self.multilineFormat = [] |
| 52 | self.outputMsg.append("package android.hardware.automotive.vehicle\n\n") |
| 53 | |
| 54 | def addRecentCommentToMsg(self): |
| 55 | self.outputMsg.extend(self.recentComments) |
| 56 | self.recentComments = [] |
| 57 | |
| 58 | def addToMsg(self, msg): |
| 59 | self.outputMsg.append(msg) |
| 60 | |
| 61 | def printOutputMsg(self): |
| 62 | msg = "".join(self.outputMsg) |
| 63 | print(msg) |
| 64 | |
| 65 | def parseLine(self, line): |
| 66 | if self.inComment: |
| 67 | self.recentComments.append(line) |
| 68 | if RE_COMMENT_END.match(line): |
| 69 | self.inComment = False |
| 70 | if DBG_COMMENT: |
| 71 | print("Comment end:{}".format(self.recentComments)) |
| 72 | return |
| 73 | elif RE_COMMENT_BEGIN.match(line): |
| 74 | self.recentComments = [] |
| 75 | self.recentComments.append(line) |
| 76 | if RE_COMMENT_SINGLE_LINE.match(line): |
| 77 | if DBG_COMMENT: |
| 78 | print("Single line Comment:{}".format(self.recentComments)) |
| 79 | return |
| 80 | self.inComment = True |
| 81 | if DBG_COMMENT: |
| 82 | print("Comment start") |
| 83 | return |
| 84 | |
| 85 | if self.inEnum: |
| 86 | if RE_ENUM_END.match(line): |
| 87 | self.inEnum = False |
| 88 | if DBG_ENUM: |
| 89 | print("End enum {}".format(self.currentEnumName)) |
| 90 | else: |
| 91 | matchElement = RE_ENUM_ELEMENT.match(line); |
| 92 | if matchElement: |
| 93 | elementName = matchElement.group(1) |
| 94 | elementValue = matchElement.group(2) |
| 95 | self.enumMap[self.currentEnumName + ':' + elementName] = elementValue |
| 96 | elif self.inVehicleProperty: |
| 97 | if RE_ENUM_END.match(line): |
| 98 | self.inVehicleProperty = False |
| 99 | self.addToMsg("}\n") |
| 100 | else: |
| 101 | text = line.strip() |
| 102 | if len(text) == 0: |
| 103 | self.multilineFormat = [] |
| 104 | else: |
| 105 | self.multilineFormat.append(text) |
| 106 | textToMatch = "".join(self.multilineFormat) |
| 107 | match = RE_VEHICLE_PROP_ELEMENT.match(textToMatch) |
| 108 | if match: |
| 109 | self.multilineFormat = [] |
| 110 | name = match.group(1) |
| 111 | val = match.group(2) |
| 112 | type1 = match.group(3) |
| 113 | self.addRecentCommentToMsg() |
| 114 | if type1 == None: # one line case |
| 115 | self.addToMsg(" {} = {},\n".format(name, val)) |
| 116 | else: |
| 117 | type2 = match.group(4) |
| 118 | type3 = match.group(5) |
| 119 | self.addToMsg(" {} = {} + {} + {} + {}, // {},{},{}\n".\ |
| 120 | format(name, val, self.enumMap[type1], self.enumMap[type3],\ |
| 121 | self.enumMap[type2], type1, type3, type2)) |
| 122 | else: |
| 123 | matchEnum = RE_ENUM_START.match(line) |
| 124 | if matchEnum: |
| 125 | enumName = matchEnum.group(1) |
| 126 | if enumName in ENUM_TYPE_TO_PARSE: |
| 127 | self.currentEnumName = enumName |
| 128 | self.inEnum = True |
| 129 | if DBG_ENUM: |
| 130 | print("enum {}".format(enumName)) |
| 131 | elif enumName == VEHICLE_PROP_ENUM: |
| 132 | self.inVehicleProperty = True |
| 133 | self.addRecentCommentToMsg() |
| 134 | self.addToMsg("@Backing(type=\"int\")\nenum VehicleProperty {\n") |
| 135 | if DBG_ENUM: |
| 136 | print("VehicleProperty starts, all enum values {}".format(self.enumMap)) |
| 137 | |
| 138 | |
| 139 | def main(): |
| 140 | if len(sys.argv) != 2: |
| 141 | print("Usage: {} types_hal_file".format(sys.argv[0])) |
| 142 | sys.exit(1) |
| 143 | file_name = sys.argv[1] |
| 144 | with open(file_name, 'r') as f: |
| 145 | parser = HIDLParser() |
| 146 | for line in f.readlines(): |
| 147 | parser.parseLine(line) |
| 148 | parser.printOutputMsg() |
| 149 | |
| 150 | if __name__ == "__main__": |
| 151 | main() |