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""" 21import re 22import sys 23 24ENUM_TYPE_TO_PARSE = [ "VehiclePropertyType", "VehiclePropertyGroup", "VehicleArea" ] 25VEHICLE_PROP_ENUM = "VehicleProperty" 26 27RE_COMMENT_BEGIN = re.compile("\s*\/\*\*") 28RE_COMMENT_END = re.compile("\s*\*\/") 29RE_COMMENT_SINGLE_LINE = re.compile("\s*\/\*\*.*\*\/") 30 31RE_ENUM_START = re.compile("\s*enum\s*(\w+)\s?.*\{") 32RE_ENUM_END = re.compile("\s*\}\;") 33 34RE_ENUM_ELEMENT = re.compile("\s*(\w+)\s*\=\s*(\w+),") 35 36RE_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 38DBG_COMMENT = False 39DBG_ENUM = False 40 41class 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 139def 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 150if __name__ == "__main__": 151 main() 152