move more helper from java_binding.py to btstack_parser.py

This commit is contained in:
Matthias Ringwald 2016-01-29 11:21:39 +01:00
parent bfd81087a7
commit 4b238d71c0
2 changed files with 150 additions and 25 deletions

142
tool/btstack_parser.py Executable file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env python
# BlueKitchen GmbH (c) 2014
import re
import os
# paths
bluetooth_h_path = 'src/bluetooth.h'
btstack_defines_h_path = 'src/btstack_defines.h'
daemon_cmds_c_path = 'platform/daemon/daemon_cmds.c'
hci_cmds_c_path = 'src/hci_cmd.c'
hci_cmds_h_path = 'src/hci_cmd.h'
hci_h_path = 'src/hci.h'
btstack_root = '../..'
def set_btstack_root(path):
btstack_root = path
def assert_dir(path):
if not os.access(path, os.R_OK):
os.makedirs(path)
def cap(x):
if x.lower() == 'btstack':
return 'BTstack'
acronyms = ['GAP', 'GATT', 'HCI', 'L2CAP', 'LE', 'RFCOMM', 'SM', 'SDP', 'UUID16', 'UUID128']
if x.upper() in acronyms:
return x.upper()
return x.capitalize()
def camel_case(name):
return ''.join(map(cap, name.split('_')))
def camel_case_var(name):
if name in ['uuid128', 'uuid16']:
return name
camel = camel_case(name)
return camel[0].lower() + camel[1:]
def read_defines(infile):
defines = dict()
with open (infile, 'rt') as fin:
for line in fin:
parts = re.match('#define\s+(\w+)\s+(\w*)',line)
if parts and len(parts.groups()) == 2:
(key, value) = parts.groups()
defines[key] = value
return defines
def parse_defines():
global btstack_root
defines = dict()
defines.update(read_defines(btstack_root + '/' + hci_cmds_h_path))
defines.update(read_defines(btstack_root + '/' + hci_h_path))
defines.update(read_defines(btstack_root + '/' + bluetooth_h_path))
defines.update(read_defines(btstack_root + '/' + btstack_defines_h_path))
return defines
def my_parse_events(path):
events = []
le_events = []
params = []
event_types = set()
format = None
with open (path, 'rt') as fin:
for line in fin:
parts = re.match('.*@format\s*(\w*)\s*', line)
if parts and len(parts.groups()) == 1:
format = parts.groups()[0]
parts = re.match('.*@param\s*(\w*)\s*', line)
if parts and len(parts.groups()) == 1:
param = parts.groups()[0]
params.append(param)
parts = re.match('\s*#define\s+(\w+)\s+(\w*)',line)
if parts and len(parts.groups()) == 2:
(key, value) = parts.groups()
if format != None:
if key.lower().startswith('hci_subevent_'):
le_events.append((value, key.lower().replace('hci_subevent_', 'hci_event_'), format, params))
else:
events.append((value, key, format, params))
event_types.add(key)
params = []
format = None
return (events, le_events, event_types)
def parse_events():
global btstack_root
# parse bluetooth.h to get used events
(bluetooth_events, bluetooth_le_events, bluetooth_event_types) = my_parse_events(btstack_root + '/' + bluetooth_h_path)
# parse btstack_defines to get events
(btstack_events, btstack_le_events, btstack_event_types) = my_parse_events(btstack_root + '/' + btstack_defines_h_path)
# concat lists
(events, le_events, event_types) = (bluetooth_events + btstack_events, bluetooth_le_events + btstack_le_events, bluetooth_event_types | btstack_event_types)
return (events, le_events, event_types)
def my_parse_commands(infile):
commands = []
with open (infile, 'rt') as fin:
params = []
for line in fin:
parts = re.match('.*@param\s*(\w*)\s*', line)
if parts and len(parts.groups()) == 1:
param = parts.groups()[0]
params.append(camel_case_var(param))
continue
declaration = re.match('const\s+hci_cmd_t\s+(\w+)[\s=]+', line)
if declaration:
command_name = camel_case(declaration.groups()[0])
if command_name.endswith('Cmd'):
command_name = command_name[:-len('Cmd')]
continue
definition = re.match('\s*OPCODE\\(\s*(\w+)\s*,\s+(\w+)\s*\\)\s*,\s\\"(\w*)\\".*', line)
if definition:
(ogf, ocf, format) = definition.groups()
if len(params) != len(format):
params = []
arg_counter = 1
for f in format:
arg_name = 'arg%u' % arg_counter
params.append(arg_name)
arg_counter += 1
commands.append((command_name, ogf, ocf, format, params))
params = []
continue
return commands
def parse_commands():
global btstack_root
commands = []
commands = commands = my_parse_commands(btstack_root + '/' + hci_cmds_c_path)
commands = commands = my_parse_commands(btstack_root + '/' + daemon_cmds_c_path)
return commands

View File

@ -4,7 +4,6 @@
import glob
import re
import sys
import os
import btstack_parser as parser
@ -138,21 +137,6 @@ gen_path = 'gen/' + package.replace('.', '/')
defines = dict()
defines_used = set()
def assert_dir(path):
if not os.access(path, os.R_OK):
os.makedirs(path)
def cap(x):
if x.lower() == 'btstack':
return 'BTstack'
acronyms = ['GAP', 'GATT', 'HCI', 'L2CAP', 'LE', 'RFCOMM', 'SM', 'SDP', 'UUID16', 'UUID128']
if x.upper() in acronyms:
return x.upper()
return x.capitalize()
def camel_case(name):
return ''.join(map(cap, name.split('_')))
def java_type_for_btstack_type(type):
param_types = { '1' : 'int', '2' : 'int', '3' : 'int', '4' : 'long', 'H' : 'int', 'B' : 'BD_ADDR',
'D' : 'byte []', 'E' : 'byte [] ', 'N' : 'String' , 'P' : 'byte []', 'A' : 'byte []',
@ -251,9 +235,8 @@ def java_defines_string(keys):
return '\n'.join( map(java_define_string, sorted(keys)))
def create_btstack_java(commands):
global gen_path
assert_dir(gen_path)
parser.assert_dir(gen_path)
outfile = '%s/BTstack.java' % gen_path
@ -308,7 +291,7 @@ def create_event(event_name, format, args):
for f, arg in zip(format, args):
# just remember name
if f in ['L','J']:
length_name = camel_case(arg)
length_name = parser.camel_case(arg)
if f == 'R':
# remaining data
access = java_event_getter_remaining_data.format(offset)
@ -319,22 +302,22 @@ def create_event(event_name, format, args):
else:
access = param_read[f] % offset
size = size_for_type(f)
getters += java_event_getter.format(java_type_for_btstack_type(f), camel_case(arg), access)
getters += java_event_getter.format(java_type_for_btstack_type(f), parser.camel_case(arg), access)
offset += size
to_string_args = ''
for arg in args:
to_string_args += ' t.append(", %s = ");\n' % arg
to_string_args += ' t.append(get%s());\n' % camel_case(arg)
to_string_args += ' t.append(get%s());\n' % parser.camel_case(arg)
to_string_method = java_event_to_string.format(event_name, to_string_args)
fout.write(java_event_template.format(package, event_name, getters, to_string_method))
def create_events(events):
global gen_path
gen_path_events = gen_path + '/event'
assert_dir(gen_path_events)
parser.assert_dir(gen_path_events)
for event_type, event_name, format, args in events:
event_name = camel_case(event_name)
event_name = parser.camel_case(event_name)
create_event(event_name, format, args)
def create_event_factory(events, le_events, defines):
@ -347,11 +330,11 @@ def create_event_factory(events, le_events, defines):
cases = ''
for event_type, event_name, format, args in events:
event_name = camel_case(event_name)
event_name = parser.camel_case(event_name)
cases += java_event_factory_event.format(event_type, event_name)
subcases = ''
for event_type, event_name, format, args in le_events:
event_name = camel_case(event_name)
event_name = parser.camel_case(event_name)
subcases += java_event_factory_subevent.format(event_type, event_name)
with open(outfile, 'wt') as fout: