1#!/usr/bin/env python
2#
3# Copyright (C) 2015 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"""Generate Java code from vehicle.h"""
18import os
19import re
20import sys
21
22JAVA_HEADER = \
23"""
24/*
25 * Copyright (C) 2015 The Android Open Source Project
26 *
27 * Licensed under the Apache License, Version 2.0 (the "License");
28 * you may not use this file except in compliance with the License.
29 * You may obtain a copy of the License at
30 *
31 *      http://www.apache.org/licenses/LICENSE-2.0
32 *
33 * Unless required by applicable law or agreed to in writing, software
34 * distributed under the License is distributed on an "AS IS" BASIS,
35 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36 * See the License for the specific language governing permissions and
37 * limitations under the License.
38 */
39
40//Autogenerated from vehicle.h using libvehiclenetwork/tool/vehicle_code_gen.py.
41//Do not modify manually.
42
43package com.android.car.vehiclenetwork;
44
45public class VehicleNetworkConsts {
46"""
47
48JAVA_TRAIL = \
49"""
50}
51"""
52
53RE_PROPERTY_PATTERN = r'/\*\*(.*?)\*/\n\#define\s+VEHICLE_PROPERTY_(\S+)\s+(\S+)'
54RE_ENUM_PATTERN = r'enum\s+(\S+)\s+\{\S*(.*?)\}'
55RE_ENUM_ENTRY_PATTERN = r'(\S+)\s*=\s*(.*?)[,\n]'
56
57class PropertyInfo(object):
58  def __init__(self, value, name):
59    self.value = value
60    self.name = name
61    self.type = ""
62    self.changeMode = ""
63    self.access = ""
64    self.unit = ""
65    self.startEnd = 0 # _START/END property
66
67  def __str__(self):
68    r = ["value:" + self.value]
69    r.append("name:" + self.name)
70    if self.type != "":
71      r.append("type:" + self.type)
72    if self.changeMode != "":
73      r.append("changeMode:" + self.changeMode)
74    if self.access != "":
75      r.append("access:" + self.access)
76    if self.unit != "":
77      r.append("unit:" + self.unit)
78    return " ".join(r)
79
80class EnumInfo(object):
81  def __init__(self, name):
82    self.name = name
83    self.enums = [] #(name, value) tuple
84  def addEntry(self, name, value):
85    self.enums.append((name, value))
86  def __str__(self):
87    r = [self.name + "\n"]
88    for e in self.enums:
89      r.append("  " + e[0] + ":" + e[1] + "\n")
90    return ''.join(r)
91
92def toJavaStyleName(name):
93  # do not convert if 1st letter is already upper
94  if name[0].isupper():
95    return name
96  words = name.split("_")
97  #print words
98  for i in range(len(words)):
99    w = words[i]
100    w = w[0].upper() + w[1:]
101    words[i] = w
102  return ''.join(words)
103
104JAVA_INT_DEF = "public static final int "
105def printProperties(props):
106  for p in props:
107    print JAVA_INT_DEF + p.name + " = " + p.value + ";"
108
109  #now impement getVehicleValueType
110  print \
111"""public static int getVehicleValueType(int property) {
112switch (property) {"""
113  for p in props:
114    if p.type != "":
115      print "case " + p.name + ": return VehicleValueType." + p.type + ";"
116  print \
117"""default: return VehicleValueType.VEHICLE_VALUE_TYPE_SHOUD_NOT_USE;
118}
119}
120"""
121  #now implement getVehiclePropertyName
122  print \
123"""public static String getVehiclePropertyName(int property) {
124switch (property) {"""
125  for p in props:
126    if (p.startEnd == 0):
127      print "case " + p.name + ': return "' + p.name +     '";'
128  print \
129"""default: return "UNKNOWN_PROPERTY";
130}
131}
132"""
133  #now implement getVehicleChangeMode
134  print \
135"""public static int[] getVehicleChangeMode(int property) {
136switch (property) {"""
137  for p in props:
138    if p.changeMode != "":
139      modes = p.changeMode.split('|')
140      modesString = []
141      for m in modes:
142        modesString.append("VehiclePropChangeMode." + m)
143      print "case " + p.name + ": return new int[] { " + " , ".join(modesString) + " };"
144  print \
145"""default: return null;
146}
147}
148"""
149  #now implement getVehicleAccess
150  print \
151"""public static int[] getVehicleAccess(int property) {
152switch (property) {"""
153  for p in props:
154    if p.access != "":
155      accesses = p.access.split('|')
156      accessesString = []
157      for a in accesses:
158        accessesString.append("VehiclePropAccess." + a)
159      print "case " + p.name + ": return new int[] { " + " , ".join(accessesString) + " };"
160  print \
161"""default: return null;
162}
163}
164"""
165
166def printEnum(e):
167  print "public static class " + toJavaStyleName(e.name) + " {"
168  for entry in e.enums:
169    print JAVA_INT_DEF + entry[0] + " = " + entry[1] + ";"
170  #now implement enumToString
171  print \
172"""public static String enumToString(int v) {
173switch(v) {"""
174  valueStore = []
175  for entry in e.enums:
176    # handling enum with the same value. Print only 1st one.
177    if valueStore.count(entry[1]) == 0:
178      valueStore.append(entry[1])
179      print "case " + entry[0] + ': return "' + entry[0] + '";'
180  print \
181"""default: return "UNKNOWN";
182}
183}
184}
185"""
186
187def printEnums(enums):
188  for e in enums:
189    printEnum(e)
190
191def main(argv):
192  vehicle_h_path = os.path.dirname(os.path.abspath(__file__)) + "/../../../../../hardware/libhardware/include/hardware/vehicle.h"
193  #print vehicle_h_path
194  f = open(vehicle_h_path, 'r')
195  text = f.read()
196  f.close()
197  vehicle_internal_h_path = os.path.dirname(os.path.abspath(__file__)) + "/../include/vehicle-internal.h"
198  f = open(vehicle_internal_h_path, 'r')
199  text = text + f.read()
200  f.close()
201
202  props = []
203  property_re = re.compile(RE_PROPERTY_PATTERN, re.MULTILINE | re.DOTALL)
204  for match in property_re.finditer(text):
205    words = match.group(1).split()
206    name = "VEHICLE_PROPERTY_" + match.group(2)
207    value = match.group(3)
208    if (value[0] == "(" and value[-1] == ")"):
209      value = value[1:-1]
210    prop = PropertyInfo(value, name)
211    i = 0
212    while i < len(words):
213      if words[i] == "@value_type":
214        i += 1
215        prop.type = words[i]
216      elif words[i] == "@change_mode":
217        i += 1
218        prop.changeMode = words[i]
219      elif words[i] == "@access":
220        i += 1
221        prop.access = words[i]
222      elif words[i] == "@unit":
223        i += 1
224        prop.unit = words[i]
225      elif words[i] == "@range_start" or words[i] == "@range_end":
226        prop.startEnd = 1
227      i += 1
228    props.append(prop)
229    #for p in props:
230    #  print p
231
232  enums = []
233  enum_re = re.compile(RE_ENUM_PATTERN, re.MULTILINE | re.DOTALL)
234  enum_entry_re = re.compile(RE_ENUM_ENTRY_PATTERN, re.MULTILINE)
235  for match in enum_re.finditer(text):
236    name = match.group(1)
237    info = EnumInfo(name)
238    for match_entry in enum_entry_re.finditer(match.group(2)):
239      valueName = match_entry.group(1)
240      value = match_entry.group(2)
241      #print valueName, value
242      if value[-1] == ',':
243        value = value[:-1]
244      info.addEntry(valueName, value)
245    enums.append(info)
246  #for e in enums:
247  #  print e
248  print JAVA_HEADER
249  printProperties(props)
250  printEnums(enums)
251  print JAVA_TRAIL
252if __name__ == '__main__':
253  main(sys.argv)
254
255