import argparse
import json
import os
import re
import sys
class TokenType(object):
UNKNOWN = 0
COMMENT = 1
PACKAGE = 2
IMPORT = 3
INTERFACE = 4
CALLBACK = 5
ID = 6
END_OF_FILE = 7
class Token(object):
def __init__(self, file_name, token_type, value):
self.token_type = token_type
self.value = value
self.row = 1
self.col = 1
self.file_name = file_name
def clean(self):
self.token_type = TokenType.UNKNOWN
self.value = ""
self.row = 1
self.col = 1
def dump(self):
return "<{}:{}:{}: {},'{}'>".format(self.file_name, self.row, self.col,
self.token_type, self.value)
def info(self):
return "{}:{}:{}".format(self.file_name, self.row, self.col)
class Char(object):
def __init__(self, is_eof, char):
self.is_eof = is_eof
self.char = char
def dump(self):
return "{%s, %s}" % (self.is_eof, self.char)
class Lexer(object):
_key_words = {
"package": TokenType.PACKAGE,
"import": TokenType.IMPORT,
"interface": TokenType.INTERFACE,
"callback": TokenType.CALLBACK,
}
def __init__(self, idl_file_path):
self.have_peek = False
with open(idl_file_path, 'r') as idl_file:
file_info = idl_file.read()
self.data = file_info
self.data_len = len(self.data)
self.read_index = 0
self.cur_token = Token(os.path.basename(idl_file_path),
TokenType.UNKNOWN, "")
self.cur_row = 1
self.cur_col = 1
def peek_char(self, peek_count=0):
index = self.read_index + peek_count
if index >= self.data_len:
return Char(True, '0')
return Char(False, self.data[index])
def get_char(self):
if self.read_index >= self.data_len:
return Char(True, '0')
read_index = self.read_index
self.read_index += 1
if self.data[read_index] == '\n':
self.cur_row += 1
self.cur_col = 1
else:
self.cur_col += 1
return Char(False, self.data[read_index])
def peek_token(self):
if not self.have_peek:
self.read_token()
self.have_peek = True
return self.cur_token
def get_token(self):
if not self.have_peek:
self.read_token()
self.have_peek = False
return self.cur_token
def read_token(self):
self.cur_token.clean()
while not self.peek_char().is_eof:
new_char = self.peek_char()
if new_char.char.isspace():
self.get_char()
continue
self.cur_token.row = self.cur_row
self.cur_token.col = self.cur_col
if new_char.char.isalpha() or new_char.char == '_':
self.read_id()
return
if new_char.char == '/':
self.read_comment()
return
self.cur_token.value = new_char.char
self.cur_token.token_type = TokenType.UNKNOWN
self.get_char()
return
self.cur_token.token_type = TokenType.END_OF_FILE
def read_id(self):
token_value = []
token_value.append(self.get_char().char)
while not self.peek_char().is_eof:
new_char = self.peek_char()
if new_char.char.isalpha() or new_char.char.isdigit(
) or new_char.char == '_' or new_char.char == '.':
token_value.append(new_char.char)
self.get_char()
continue
break
key = "".join(token_value)
if key in self._key_words.keys():
self.cur_token.token_type = self._key_words[key]
else:
self.cur_token.token_type = TokenType.ID
self.cur_token.value = key
def read_comment(self):
token_value = []
token_value.append(self.get_char().char)
new_char = self.peek_char()
if not new_char.is_eof:
if new_char.char == '/':
self.read_line_comment(token_value)
return
elif new_char.char == '*':
self.read_block_comment(token_value)
return
self.cur_token.token_type = TokenType.UNKNOWN
self.cur_token.value = "".join(token_value)
def read_line_comment(self, token_value):
token_value.append(self.get_char().char)
while not self.peek_char().is_eof:
new_char = self.get_char()
if new_char.char == '\n':
break
token_value.append(new_char.char)
self.cur_token.token_type = TokenType.COMMENT
self.cur_token.value = "".join(token_value)
def read_block_comment(self, token_value):
token_value.append(self.get_char().char)
while not self.peek_char().is_eof:
new_char = self.get_char()
token_value.append(new_char.char)
if new_char.char == '*' and self.peek_char().char == '/':
token_value.append(self.get_char().char)
break
value = "".join(token_value)
if value.endswith("*/"):
self.cur_token.token_type = TokenType.COMMENT
else:
self.cur_token.token_type = TokenType.UNKNOWN
self.cur_token.value = value
class ModuleInfo(object):
package = ""
version = ""
include_dirs = set()
out_dir = ""
sources = []
proxy_sources = []
stub_sources = []
proxy_deps = []
stub_deps = []
header_deps = []
@staticmethod
def json_info():
include_dirs_ret = sorted(list(ModuleInfo.include_dirs))
ModuleInfo.sources.sort()
ModuleInfo.proxy_sources.sort()
ModuleInfo.stub_sources.sort()
result = {
"package": ModuleInfo.package,
"version": ModuleInfo.version,
"include_dirs": include_dirs_ret,
"out_dir": ModuleInfo.out_dir,
"sources": ModuleInfo.sources,
"proxy_sources": ModuleInfo.proxy_sources,
"stub_sources": ModuleInfo.stub_sources,
"proxy_deps": ModuleInfo.proxy_deps,
"stub_deps": ModuleInfo.stub_deps,
"header_deps": ModuleInfo.header_deps,
}
return json.dumps(result)
class Option(object):
system = "full"
mode = "ipc"
language = "cpp"
gen_dir = ""
root_package = ""
root_path = ""
idl_sources = []
imports = []
@staticmethod
def load(opt_args):
Option.system = opt_args.system
Option.mode = opt_args.mode
Option.language = opt_args.language
if opt_args.out == "":
raise Exception(
"the gen_dir '{}' is empty, please check input".format(
opt_args.out))
else:
Option.gen_dir = opt_args.out
map_result = opt_args.root.split(":")
if len(map_result) != 2:
raise Exception(
"the package path '{}' is valid, please check input".format(
opt_args.root))
else:
Option.root_package = map_result[0]
Option.root_path = map_result[1]
if len(opt_args.file) == 0:
raise Exception("the idl sources is empty, please check input")
else:
Option.idl_sources = opt_args.file
if opt_args.imports is not None:
Option.imports = opt_args.imports
@staticmethod
def dump():
result = {
"system": Option.system,
"kernel": Option.kernel,
"mode": Option.mode,
"language": Option.language,
"gen_dir": Option.gen_dir,
"root_package": Option.root_package,
"root_path": Option.root_path,
"idl_sources": Option.idl_sources
}
return json.dumps(result)
class IdlType(object):
INTERFACE = 1
CALL_INTERFACE = 2
CALLBACK = 3
TYPES = 4
class IdlDetail(object):
def __init__(self, path):
self.package = ""
self.idl_type = IdlType.TYPES
self.imports = []
self.file_path = path
self.file_name = os.path.basename(self.file_path)
self.name = self.file_name.split('.')[0]
def full_name(self):
return "{}.{}".format(self.package, self.name)
def dump(self):
result = {
"package": self.package,
"type": self.idl_type,
"imports": self.imports,
"path": self.file_path
}
return json.dumps(result)
class IdlParser(object):
def parse(self, ):
all_idl_details = {}
if Option.language == "c":
self.parse_c_idl_files(all_idl_details)
self.parse_deps(all_idl_details)
self.parse_module_info(all_idl_details)
return
for idl_file in Option.idl_sources:
idl_detail = self.parse_one(idl_file)
all_idl_details[idl_detail.full_name()] = idl_detail
self.parse_deps(all_idl_details)
self.parse_module_info(all_idl_details)
def parse_one(self, file_path):
cur_idl_detail = IdlDetail(file_path)
lex = Lexer(file_path)
while lex.peek_token().token_type != TokenType.END_OF_FILE:
cur_token_type = lex.peek_token().token_type
if cur_token_type == TokenType.PACKAGE:
self.parse_package(lex, cur_idl_detail)
elif cur_token_type == TokenType.IMPORT:
self.parse_import(lex, cur_idl_detail)
elif cur_token_type == TokenType.CALLBACK:
cur_idl_detail.idl_type = IdlType.CALLBACK
lex.get_token()
elif cur_token_type == TokenType.INTERFACE:
self.parse_interface(lex, cur_idl_detail)
else:
lex.get_token()
return cur_idl_detail
def parse_c_idl_files(self, all_idl_details):
idl_sources_set = set()
idl_queue = []
for idl_file in Option.idl_sources:
idl_queue.append(idl_file)
while len(idl_queue) > 0:
cur_idl_file = idl_queue.pop(0)
if cur_idl_file in idl_sources_set:
continue
idl_sources_set.add(cur_idl_file)
self.parse_c_idl_files_import(cur_idl_file, idl_queue)
for idl_file in idl_sources_set:
idl_detail = self.parse_one(idl_file)
all_idl_details[idl_detail.full_name()] = idl_detail
self.merged_idl_details(all_idl_details)
def parse_c_idl_files_import(self, file_path, idl_queue):
lex = Lexer(file_path)
while lex.peek_token().token_type != TokenType.END_OF_FILE:
cur_token_type = lex.peek_token().token_type
if cur_token_type == TokenType.IMPORT:
lex.get_token()
token = lex.peek_token()
if lex.peek_token().token_type != TokenType.ID:
raise Exception("{}: expected package name before '{}'".format(
token.info(), token.value))
idl_queue.append(
CodeGen.get_package_path(token.value) + ".idl")
lex.get_token()
def update_imports(self, all_idl_details, idl_detail, merged_details):
if idl_detail.full_name() not in merged_details:
imports = []
for import_name in idl_detail.imports:
import_idl = all_idl_details[import_name]
if import_idl.full_name() in imports:
continue
if import_idl.full_name() != idl_detail.full_name():
imports.append(import_idl.full_name())
idl_detail.imports = imports
merged_details[idl_detail.full_name()] = idl_detail
else:
for import_name in idl_detail.imports:
import_idl = all_idl_details[import_name]
merged_detail = merged_details[idl_detail.full_name()]
if import_idl.full_name() in merged_detail.imports:
continue
if import_idl.full_name() != idl_detail.full_name():
merged_detail.imports.append(import_idl.full_name())
def merged_idl_details(self, all_idl_details):
merged_details = {}
source_idl_detail = self.parse_one(Option.idl_sources[0])
for _, idl_detail in all_idl_details.items():
idl_detail.package = source_idl_detail.package
idl_detail.version = source_idl_detail.version
for _, idl_detail in all_idl_details.items():
self.update_imports(all_idl_details, idl_detail, merged_details)
all_idl_details.clear()
for key, value in merged_details.items():
all_idl_details[key] = value
def parse_package(self, lex, cur_idl_detail):
lex.get_token()
token = lex.peek_token()
if token.token_type != TokenType.ID:
raise Exception("{}: expected package name before '{}'".format(
token.info(), token.value))
token = lex.get_token()
if not self.parse_version(token.value, cur_idl_detail):
raise Exception("{}: failed to parse package name '{}'".format(
token.info(), token.vlaue))
def parse_version(self, package_name, cur_idl_detail):
result = re.findall(r'\w+(?:\.\w+)*\.[V|v](\d+)_(\d+)', package_name)
if len(result) > 0:
cur_idl_detail.package = package_name
major_version = result[0][0]
minor_version = result[0][1]
cur_idl_detail.version = "{}.{}".format(major_version, minor_version)
return True
return False
def parse_import(self, lex, cur_idl_detail):
lex.get_token()
if lex.peek_token().token_type != TokenType.ID:
token = lex.peek_token()
raise Exception("{}: expected package name before '{}'".format(
token.info(), token.value))
cur_idl_detail.imports.append(lex.get_token().value)
def parse_interface(self, lex, cur_idl_detail):
lex.get_token()
if lex.peek_token().token_type != TokenType.ID:
token = lex.peek_token()
raise Exception("{}: expected interface name before '{}'".format(
token.info(), token.value))
token = lex.get_token()
interface_name = token.value
if interface_name != cur_idl_detail.name:
raise Exception(
"{}: interface name '{}' does not match file name '{}'".format(
token.info(), interface_name, cur_idl_detail.file_name))
if cur_idl_detail.idl_type != IdlType.CALLBACK:
cur_idl_detail.idl_type = IdlType.INTERFACE
def parse_deps(self, all_idl_details):
for detail_name, idl_detail in all_idl_details.items():
self.query_and_update_idl_type(idl_detail, all_idl_details)
def query_and_update_idl_type(self, idl_detail, all_idl_details):
for other_name, other_detail in all_idl_details.items():
if idl_detail.full_name() == other_name:
continue
if self.imported_by_other_idl(idl_detail, other_detail) and idl_detail.idl_type == IdlType.INTERFACE:
idl_detail.idl_type = IdlType.CALL_INTERFACE
break
def imported_by_other_idl(self, idl_detail, other_detail):
for import_name in other_detail.imports:
if idl_detail.full_name() == import_name:
return True
return False
def parse_module_info(self, all_idl_details):
generator = CodeGenFactory.create_code_generate()
if generator is None:
return
ModuleInfo.out_dir = Option.gen_dir
self.parse_sources(all_idl_details, generator)
ModuleInfo.proxy_deps, ModuleInfo.stub_deps, ModuleInfo.header_deps = CodeGen.get_lib_deps(Option.imports)
def parse_sources(self, all_idl_details, generator):
ModuleInfo.include_dirs.add(Option.gen_dir)
for idl_detail in all_idl_details.values():
ModuleInfo.package = idl_detail.package
ModuleInfo.version = idl_detail.version
ModuleInfo.include_dirs.add(
generator.parse_include_dirs(idl_detail.package))
sources, proxy_sources, sub_sources = generator.gen_code(
idl_detail)
ModuleInfo.sources.extend(sources)
ModuleInfo.proxy_sources.extend(proxy_sources)
ModuleInfo.stub_sources.extend(sub_sources)
class CodeGen(object):
@staticmethod
def get_sub_package(package):
if package.startswith(Option.root_package):
root_package_len = len(Option.root_package)
return package[root_package_len + 1:]
return package
@staticmethod
def get_package_path(package):
package_path = ""
if package.startswith(Option.root_package):
root_package_len = len(Option.root_package)
sub_package = package[root_package_len:]
sub_package_path = sub_package.replace(".", os.sep)
package_path = "{}{}".format(Option.root_path, sub_package_path)
else:
raise Exception("find root package '{}' failed in '{}'".format(
Option.root_package, package))
return package_path
@staticmethod
def get_version(package):
major_version = 0
minor_version = 0
result = re.findall(r'\w+(?:\.\w+)*\.[V|v](\d+)_(\d+)', package)
if len(result) > 0:
major_version = result[0][0]
minor_version = result[0][1]
return major_version, minor_version
@staticmethod
def parse_include_dirs(package):
sub_package = CodeGen.get_sub_package(package)
last_point_index = sub_package.rfind('.')
package_without_version = sub_package[:last_point_index]
package_dir_without_version = package_without_version.replace(
'.', os.sep)
return os.path.join(Option.gen_dir, package_dir_without_version)
@staticmethod
def get_source_file_dir(package):
sub_package = CodeGen.get_sub_package(package)
sub_package_dir = "{}{}".format(sub_package.replace('.', os.sep),
os.sep)
return os.path.join(Option.gen_dir, sub_package_dir)
@staticmethod
def translate_file_name(file_name):
under_line = '_'
result = []
name_len = len(file_name)
for index in range(name_len):
cur_char = file_name[index]
if cur_char.isupper():
if index > 1:
result.append(under_line)
result.append(cur_char.lower())
else:
result.append(cur_char)
return "".join(result)
@staticmethod
def translate_proxy_name(base_name):
temp_name = "{}Proxy".format(base_name)
return CodeGen.translate_file_name(temp_name)
@staticmethod
def translate_stub_name(base_name):
temp_name = "{}Stub".format(base_name)
return CodeGen.translate_file_name(temp_name)
@staticmethod
def translate_service_name(base_name):
temp_name = "{}Service".format(base_name)
return CodeGen.translate_file_name(temp_name)
@staticmethod
def translate_driver_name(base_name):
temp_name = "{}Driver".format(base_name)
return CodeGen.translate_file_name(temp_name)
@staticmethod
def get_type_names(name):
base_name = CodeGen.translate_file_name(name)
return base_name
@staticmethod
def get_file_names(idl_detail):
interface_name = ""
proxy_name = ""
stub_name = ""
service_name = ""
driver_name = ""
types_name = ""
if idl_detail.idl_type == IdlType.TYPES:
types_name = CodeGen.get_type_names(idl_detail.name)
return interface_name, proxy_name, stub_name, service_name, driver_name, types_name
base_name = idl_detail.name[1:] if idl_detail.name.startswith(
"I") else idl_detail.name
interface_name = CodeGen.translate_file_name(idl_detail.name)
proxy_name = CodeGen.translate_proxy_name(base_name)
stub_name = CodeGen.translate_stub_name(base_name)
service_name = CodeGen.translate_service_name(base_name)
driver_name = CodeGen.translate_driver_name(base_name)
if idl_detail.idl_type == IdlType.INTERFACE:
driver_name = CodeGen.translate_driver_name(base_name)
return interface_name, proxy_name, stub_name, service_name, driver_name, types_name
@staticmethod
def header_file(file_dir, name):
return os.path.join(file_dir, "{}.h".format(name))
@staticmethod
def c_source_file(file_dir, name):
return os.path.join(file_dir, "{}.c".format(name))
@staticmethod
def cpp_source_file(file_dir, name):
return os.path.join(file_dir, "{}.cpp".format(name))
@staticmethod
def get_import(imp):
package = ""
module_name = ""
imp_result = imp.split(":")
if len(imp_result) == 2:
package = imp_result[0]
module_name = imp_result[1]
return package, module_name
@staticmethod
def get_lib_deps(imports):
proxy_deps = []
stub_deps = []
header_deps = []
for imps in imports:
package, module_name = CodeGen.get_import(imps)
package_path = CodeGen.get_package_path(package)
major_version, minor_version = CodeGen.get_version(package)
proxy_lib_name = "lib{}_proxy_{}.{}".format(module_name, major_version, minor_version)
stub_lib_name = "lib{}_stub_{}.{}".format(module_name, major_version, minor_version)
header_config = "{}_idl_headers_{}.{}".format(module_name, major_version, minor_version)
proxy_lib_dep = "{}:{}".format(package_path, proxy_lib_name)
stub_lib_dep = "{}:{}".format(package_path, stub_lib_name)
header_dep = "{}:{}".format(package_path, header_config)
proxy_deps.append(proxy_lib_dep)
stub_deps.append(stub_lib_dep)
header_deps.append(header_dep)
return proxy_deps, stub_deps, header_deps
def gen_code(self, idl_detail):
idl_detail
return [], [], []
class LowCCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
interface_name, _, _, service_name, driver_name, types_name = self.get_file_names(idl_detail)
if idl_detail.idl_type == IdlType.TYPES:
header_file = self.header_file(file_dir, types_name)
sources.append(header_file)
if idl_detail.idl_type == IdlType.INTERFACE:
header_file = self.header_file(file_dir, interface_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.c_source_file(file_dir, service_name)
driver_source_file = self.c_source_file(file_dir, driver_name)
sources.extend([header_file, service_header_file, service_source_file, driver_source_file])
return sources, [], []
class LowCppCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
interface_name, _, _, service_name, driver_name, types_name = self.get_file_names(idl_detail)
if idl_detail.idl_type == IdlType.TYPES:
header_file = self.header_file(file_dir, types_name)
sources.append(header_file)
if idl_detail.idl_type == IdlType.INTERFACE:
header_file = self.header_file(file_dir, interface_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.cpp_source_file(file_dir, service_name)
driver_source_file = self.cpp_source_file(file_dir, driver_name)
sources.extend([header_file, service_header_file, service_source_file, driver_source_file])
return sources, [], []
class KernelCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
proxy_sources = []
stub_sources = []
interface_name, proxy_name, stub_name, service_name, driver_name, types_name = self.get_file_names(
idl_detail)
if idl_detail.idl_type == IdlType.TYPES:
header_file = self.header_file(file_dir, types_name)
source_file = self.c_source_file(file_dir, types_name)
sources.extend([header_file, source_file])
proxy_sources.append(source_file)
stub_sources.append(source_file)
return sources, proxy_sources, stub_sources
if idl_detail.idl_type == IdlType.INTERFACE:
iface_header_file = self.header_file(file_dir, interface_name)
proxy_source_file = self.c_source_file(file_dir, proxy_name)
stub_header_file = self.header_file(file_dir, stub_name)
stub_source_file = self.c_source_file(file_dir, stub_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.c_source_file(file_dir, service_name)
driver_source_file = self.c_source_file(file_dir, driver_name)
sources.extend([
iface_header_file, proxy_source_file, stub_header_file,
stub_source_file, service_header_file, service_source_file,
driver_source_file
])
proxy_sources.append(proxy_source_file)
stub_sources.append(stub_source_file)
return sources, proxy_sources, stub_sources
class PassthroughCCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
proxy_sources = []
stub_sources = []
interface_name, proxy_name, _, service_name, _, types_name = self.get_file_names(
idl_detail)
iface_header_file = self.header_file(file_dir, interface_name)
proxy_source_file = self.c_source_file(file_dir, proxy_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.c_source_file(file_dir, service_name)
types_header_file = self.header_file(file_dir, types_name)
if idl_detail.idl_type == IdlType.INTERFACE:
sources.extend(
[iface_header_file, proxy_source_file, service_source_file])
proxy_sources.append(proxy_source_file)
elif idl_detail.idl_type == IdlType.CALL_INTERFACE:
sources.extend(
[iface_header_file, service_header_file, service_source_file])
elif idl_detail.idl_type == IdlType.CALLBACK:
sources.extend(
[iface_header_file, service_header_file, service_source_file])
else:
sources.append(types_header_file)
return sources, proxy_sources, stub_sources
class PassthroughCppCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
proxy_sources = []
stub_sources = []
interface_name, proxy_name, _, service_name, _, types_name = self.get_file_names(
idl_detail)
iface_header_file = self.header_file(file_dir, interface_name)
proxy_source_file = self.cpp_source_file(file_dir, proxy_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.cpp_source_file(file_dir, service_name)
types_header_file = self.header_file(file_dir, types_name)
if idl_detail.idl_type == IdlType.INTERFACE:
sources.extend([
iface_header_file, proxy_source_file, service_header_file,
service_source_file
])
proxy_sources.append(proxy_source_file)
elif idl_detail.idl_type == IdlType.CALL_INTERFACE:
sources.extend(
[iface_header_file, service_header_file, service_source_file])
elif idl_detail.idl_type == IdlType.CALLBACK:
sources.extend(
[iface_header_file, service_header_file, service_source_file])
else:
sources.append(types_header_file)
return sources, proxy_sources, stub_sources
class IpcCCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
proxy_sources = []
stub_sources = []
interface_name, proxy_name, stub_name, service_name, driver_name, types_name = self.get_file_names(
idl_detail)
iface_header_file = self.header_file(file_dir, interface_name)
proxy_source_file = self.c_source_file(file_dir, proxy_name)
stub_header_file = self.header_file(file_dir, stub_name)
stub_source_file = self.c_source_file(file_dir, stub_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.c_source_file(file_dir, service_name)
driver_source_file = self.c_source_file(file_dir, driver_name)
types_header_file = self.header_file(file_dir, types_name)
types_source_file = self.c_source_file(file_dir, types_name)
if idl_detail.idl_type == IdlType.INTERFACE:
sources.extend([
iface_header_file, proxy_source_file, stub_header_file,
stub_source_file, service_source_file, driver_source_file
])
proxy_sources.append(proxy_source_file)
stub_sources.append(stub_source_file)
elif idl_detail.idl_type == IdlType.CALL_INTERFACE:
sources.extend([
iface_header_file, proxy_source_file, stub_header_file,
stub_source_file, service_header_file, service_source_file
])
proxy_sources.append(proxy_source_file)
stub_sources.append(stub_source_file)
elif idl_detail.idl_type == IdlType.CALLBACK:
sources.extend([
iface_header_file, proxy_source_file, stub_header_file,
stub_source_file, service_header_file, service_source_file
])
proxy_sources.append(stub_source_file)
stub_sources.append(proxy_source_file)
else:
sources.extend([types_header_file, types_source_file])
proxy_sources.append(types_source_file)
stub_sources.append(types_source_file)
return sources, proxy_sources, stub_sources
class IpcCppCodeGen(CodeGen):
def gen_code(self, idl_detail):
file_dir = self.get_source_file_dir(idl_detail.package)
sources = []
proxy_sources = []
stub_sources = []
interface_name, proxy_name, stub_name, service_name, driver_name, types_name = self.get_file_names(
idl_detail)
iface_header_file = self.header_file(file_dir, interface_name)
proxy_header_file = self.header_file(file_dir, proxy_name)
proxy_source_file = self.cpp_source_file(file_dir, proxy_name)
stub_header_file = self.header_file(file_dir, stub_name)
stub_source_file = self.cpp_source_file(file_dir, stub_name)
service_header_file = self.header_file(file_dir, service_name)
service_source_file = self.cpp_source_file(file_dir, service_name)
driver_source_file = self.cpp_source_file(file_dir, driver_name)
types_header_file = self.header_file(file_dir, types_name)
types_source_file = self.cpp_source_file(file_dir, types_name)
if idl_detail.idl_type == IdlType.INTERFACE:
sources.extend([
iface_header_file, proxy_header_file, proxy_source_file,
stub_header_file, stub_source_file, service_header_file,
service_source_file, driver_source_file
])
proxy_sources.append(proxy_source_file)
stub_sources.append(stub_source_file)
elif idl_detail.idl_type == IdlType.CALL_INTERFACE:
sources.extend([
iface_header_file, proxy_header_file, proxy_source_file,
stub_header_file, stub_source_file, service_header_file,
service_source_file
])
proxy_sources.append(proxy_source_file)
stub_sources.append(stub_source_file)
elif idl_detail.idl_type == IdlType.CALLBACK:
sources.extend([
iface_header_file, proxy_header_file, proxy_source_file,
stub_header_file, stub_source_file, service_header_file,
service_source_file
])
proxy_sources.append(stub_source_file)
stub_sources.append(proxy_source_file)
else:
sources.extend([types_header_file, types_source_file])
proxy_sources.append(types_source_file)
stub_sources.append(types_source_file)
return sources, proxy_sources, stub_sources
class CodeGenFactory(object):
action_config = {
"mini": {
"low": {
"c": LowCCodeGen(),
"cpp": LowCppCodeGen()
}
},
"lite": {
"kernel": {
"c": KernelCodeGen()
},
"passthrough": {
"c": PassthroughCCodeGen(),
"cpp": PassthroughCppCodeGen()
}
},
"full": {
"kernel": {
"c": KernelCodeGen()
},
"passthrough": {
"c": PassthroughCCodeGen(),
"cpp": PassthroughCppCodeGen()
},
"ipc": {
"c": IpcCCodeGen(),
"cpp": IpcCppCodeGen()
}
}
}
@staticmethod
def create_code_generate():
if Option.system not in CodeGenFactory.action_config:
raise Exception("the '{}' system is not supported".format(
Option.system))
system_action = CodeGenFactory.action_config.get(
Option.system)
if Option.mode not in system_action:
raise Exception(
"the '{}' mode is not supported by '{}' system".format(
Option.mode, Option.system))
mode_action = system_action.get(Option.mode)
if Option.language not in mode_action:
raise Exception(
"the '{}' language is not support by '{}' mode of '{}' system"
.format(Option.language, Option.mode, Option.system))
return mode_action.get(Option.language)
def check_python_version():
if sys.version_info < (3, 0):
raise Exception("Please run with python version >= 3.0")
if __name__ == "__main__":
check_python_version()
option_parser = argparse.ArgumentParser(
description="Tools for generating compilation infomation of idl files",
)
option_parser.add_argument("-s",
"--system",
choices=["mini", "lite", "full"],
default="full",
help="system: mini, lite, full")
option_parser.add_argument(
"-m",
"--mode",
choices=["ipc", "passthrough", "kernel", "low"],
default="ipc",
help="generate code of ipc, passthrough or kernel mode")
option_parser.add_argument("-l",
"--language",
required=True,
choices=["c", "cpp"],
help="language of generating code")
option_parser.add_argument("-o",
"--out",
required=True,
default=".",
help="direstory of generate file")
option_parser.add_argument("-r",
"--root",
required=True,
help="mapping path: <root package>:<path>")
option_parser.add_argument("-f",
"--file",
required=True,
action="append",
help="the idl file")
option_parser.add_argument("--imports",
action="append",
help="the imports")
Option.load(option_parser.parse_args())
idl_parser = IdlParser()
idl_parser.parse()
sys.stdout.write(ModuleInfo.json_info())
sys.stdout.flush()