Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • card10/firmware
  • annejan/firmware
  • astro/firmware
  • fpletz/firmware
  • gerd/firmware
  • fleur/firmware
  • swym/firmware
  • l/firmware
  • uberardy/firmware
  • wink/firmware
  • madonius/firmware
  • mot/firmware
  • filid/firmware
  • q3k/firmware
  • hauke/firmware
  • Woazboat/firmware
  • pink/firmware
  • mossmann/firmware
  • omniskop/firmware
  • zenox/firmware
  • trilader/firmware
  • Danukeru/firmware
  • shoragan/firmware
  • zlatko/firmware
  • sistason/firmware
  • datenwolf/firmware
  • bene/firmware
  • amedee/firmware
  • martinling/firmware
  • griffon/firmware
  • chris007/firmware
  • adisbladis/firmware
  • dbrgn/firmware
  • jelly/firmware
  • rnestler/firmware
  • mh/firmware
  • ln/firmware
  • penguineer/firmware
  • monkeydom/firmware
  • jens/firmware
  • jnaulty/firmware
  • jeffmakes/firmware
  • marekventur/firmware
  • pete/firmware
  • h2obrain/firmware
  • DooMMasteR/firmware
  • jackie/firmware
  • prof_r/firmware
  • Draradech/firmware
  • Kartoffel/firmware
  • hinerk/firmware
  • abbradar/firmware
  • JustTB/firmware
  • LuKaRo/firmware
  • iggy/firmware
  • ente/firmware
  • flgr/firmware
  • Lorphos/firmware
  • matejo/firmware
  • ceddral7/firmware
  • danb/firmware
  • joshi/firmware
  • melle/firmware
  • fitch/firmware
  • deurknop/firmware
  • sargon/firmware
  • markus/firmware
  • kloenk/firmware
  • lucaswerkmeister/firmware
  • derf/firmware
  • meh/firmware
  • dx/card10-firmware
  • torben/firmware
  • yuvadm/firmware
  • AndyBS/firmware
  • klausdieter1/firmware
  • katzenparadoxon/firmware
  • xiretza/firmware
  • ole/firmware
  • techy/firmware
  • thor77/firmware
  • TilCreator/firmware
  • fuchsi/firmware
  • dos/firmware
  • yrlf/firmware
  • PetePriority/firmware
  • SuperVirus/firmware
  • sur5r/firmware
  • tazz/firmware
  • Alienmaster/firmware
  • flo_h/firmware
  • baldo/firmware
  • mmu_man/firmware
  • Foaly/firmware
  • sodoku/firmware
  • Guinness/firmware
  • ssp/firmware
  • led02/firmware
  • Stormwind/firmware
  • arist/firmware
  • coon/firmware
  • mdik/firmware
  • pippin/firmware
  • royrobotiks/firmware
  • zigot83/firmware
  • mo_k/firmware
106 results
Select Git revision
Show changes
Commits on Source (1)
...@@ -4,33 +4,76 @@ import os ...@@ -4,33 +4,76 @@ import os
import re import re
import subprocess import subprocess
api_src_fmt = """\
#define API(id, def) __GENERATE_API $ __GEN_ID_##id $ def $
#include "{header}"
"""
def main():
parser = argparse.ArgumentParser( """Generated Client file"""
description="Generate the API stubs from a header file." api_func_start_fmt = """\
) /* Autogenerated stub for {id} */
parser.add_argument( void {cdecl}({cargs})
"-H", "--header", required=True, help="The header to base the definitions on." {{
) const int size = {total_size};
parser.add_argument( void*buffer;
"-c", "--client", required=True, help="The output client-side c source file."
) buffer = api_call_start({id}, size);
parser.add_argument( /* TODO: Check if buffer is no NULL */
"-s", "--server", required=True, help="The output server-side c source file." """
serialise_arg_fmt = """ *({type}*)(buffer + {offset}) = {arg};"""
bother_dispatcher_fmt = """
printf("Sending call {id}\\nBUF: ");
for (int i = 0; i < size; i++) {{
printf("0x%02x ", ((char*)buffer)[i]);
}}
printf("\\n");
api_call_bother_dispatcher(buffer);
}}
"""
"""Generated Service file"""
api_dispatch_call_start = """\
void __api_dispatch_call(uint32_t id, void*buffer)
{
switch (id) {"""
dispatch_case_fmt = """\
case {id}:
{cdecl}("""
deserialise_arg_fmt = """\
*({type}*)(buffer + {offset})"""
insert_switch_case_break_str = """
);
break;"""
switch_add_default_fmt = """\
default:
printf("Error: API function %x is unknown!!\\n", {id});
break;
}}
}}"""
def api_func_iter (header:str):
# Parse the header for API definitions
matcher = re.compile(
r"__GENERATE_API \$ __GEN_ID_(?P<id>\w+) \$ void (?P<decl>.+?)\((?P<args>.*?)\) \$",
re.DOTALL | re.MULTILINE,
) )
args = parser.parse_args()
with contextlib.ExitStack() as cx:
# Run the preprocessor on the header file to get the API definitions. # Run the preprocessor on the header file to get the API definitions.
# #
# For this, we first need a source to include the header which contains # For this, we first need a source to include the header which contains
# an alternative definition of the `API` macro that marks definitions in # an alternative definition of the `API` macro that marks definitions in
# a way we can find later on. # a way we can find later on.
api_src = """\ api_src = api_src_fmt.format(
#define API(id, def) __GENERATE_API $ __GEN_ID_##id $ def $ header=os.path.relpath(header)
#include "{header}"
""".format(
header=os.path.relpath(args.header)
) )
# Evaluate the preprocessor # Evaluate the preprocessor
...@@ -38,130 +81,133 @@ def main(): ...@@ -38,130 +81,133 @@ def main():
["gcc", "-E", "-"], input=api_src.encode() ["gcc", "-E", "-"], input=api_src.encode()
).decode() ).decode()
# Parse the header for API definitions return matcher.finditer(source)
matcher = re.compile(
r"__GENERATE_API \$ __GEN_ID_(?P<id>\w+) \$ void (?P<decl>.+?)\((?P<args>.*?)\) \$",
re.DOTALL | re.MULTILINE,
)
args_matcher = re.compile(r"(?P<type>\w+(?:\*+|\s+))(?P<name>\w+),")
# Open output files
f_client = cx.enter_context(open(args.client, "w"))
f_server = cx.enter_context(open(args.server, "w"))
def include_header (header:str, file):
print('#include "{}"\n'.format( print('#include "{}"\n'.format(
os.path.basename(args.header) os.path.basename(header)
), file=f_client) ), file=file)
print("""\
#include "{}"
void __api_dispatch_call(uint32_t id, void*buffer)
{{
switch (id) {{""".format(
os.path.basename(args.header)
), file=f_server)
for match in matcher.finditer(source):
api_id = match.group("id")
api_decl = match.group("decl")
api_args = match.group("args")
def destructure_args (api_args:str):
api_args_names = [] api_args_names = []
api_args_types = [] api_args_types = []
api_args_sizes = [] api_args_sizes = []
args_matcher = re.compile(r"(?P<type>\w+(?:\*+|\s+))(?P<name>\w+),")
# Destructure args # Destructure args
for match in args_matcher.finditer(api_args + ","): for arg in args_matcher.finditer(api_args + ","):
arg_type = match.group("type").strip() arg_type = arg.group("type").strip()
arg_name = match.group("name") arg_name = arg.group("name")
api_args_names.append(arg_name) api_args_names.append(arg_name)
api_args_types.append(arg_type) api_args_types.append(arg_type)
api_args_sizes.append("sizeof({})".format(arg_type)) api_args_sizes.append("sizeof({})".format(arg_type))
print( return (api_args_names, api_args_types, api_args_sizes)
"""\
/* Autogenerated stub for {id} */
void {cdecl}({cargs})
{{
const int size = {total_size};
void*buffer;
buffer = api_call_start({id}, size);
/* TODO: Check if buffer is no NULL */
""".format(
id=api_id,
cdecl=api_decl,
cargs=api_args,
total_size=" + ".join(api_args_sizes),
),
file=f_client,
)
print("""\
case {id}:
{cdecl}(""".format(id=api_id, cdecl=api_decl),
file=f_server,
)
for i, (arg, ty) in enumerate(zip(api_args_names, api_args_types)): def serialise_arg (ty:str, api_args_sizes:list, arg_idx:int, arg:str, file):
print( print(
""" *({type}*)(buffer + {offset}) = {arg};""".format( serialise_arg_fmt.format(
type=ty, type=ty,
offset=" + ".join(api_args_sizes[:i]) if i > 0 else "0", offset=" + ".join(api_args_sizes[:arg_idx]) if arg_idx > 0 else "0",
arg=arg, arg=arg,
), ),
file=f_client, file=file,
) )
if i != 0: def deserialise_arg (ty:str, api_args_sizes:list, arg_idx:int, file):
print(",", file=f_server) if arg_idx != 0:
print(",", file=file)
print( print(
"""\ deserialise_arg_fmt.format(
*({type}*)(buffer + {offset})""".format(
type=ty, type=ty,
offset=" + ".join(api_args_sizes[:i]) if i > 0 else "0", offset=" + ".join(api_args_sizes[:arg_idx]) if arg_idx > 0 else "0",
), ),
file=f_server, file=file,
end="", end="",
) )
print("""
); def insert_switch_case_break (file):
break;""".format( print(insert_switch_case_break_str,
cdecl=api_decl, file=file,
args=", ".join(api_args_names),
),
file=f_server,
) )
print(
"""
printf("Sending call {id}\\nBUF: ");
for (int i = 0; i < size; i++) {{
printf("0x%02x ", ((char*)buffer)[i]);
}}
printf("\\n");
api_call_bother_dispatcher(buffer); def bother_dispatcher (api_id:str, file):
}} print(bother_dispatcher_fmt.format(
""".format(
id=api_id id=api_id
), ),
file=f_client, file=file,
) )
print("""\
default: def switch_add_default (api_id:str, file):
printf("Error: API function %x is unknown!!\\n", {id}); print(switch_add_default_fmt.format(
break;
}}
}}""".format(
id=api_id, id=api_id,
), file=f_server) ), file=file)
def main():
parser = argparse.ArgumentParser(
description="Generate the API stubs from a header file."
)
parser.add_argument(
"-H", "--header", required=True, help="The header to base the definitions on."
)
parser.add_argument(
"-c", "--client", required=True, help="The output client-side c source file."
)
parser.add_argument(
"-s", "--server", required=True, help="The output server-side c source file."
)
args = parser.parse_args()
# Open output files
cx = contextlib.ExitStack()
f_client = cx.enter_context(open(args.client, "w"))
f_server = cx.enter_context(open(args.server, "w"))
include_header (args.header, f_client)
include_header (args.header, f_server)
print(api_dispatch_call_start, file=f_server)
for api_func in api_func_iter (args.header):
api_id = api_func.group("id")
api_decl = api_func.group("decl")
api_args = api_func.group("args")
(api_args_names, api_args_types, api_args_sizes) = \
destructure_args (api_args)
print(api_func_start_fmt.format(
id=api_id,
cdecl=api_decl,
cargs=api_args,
total_size=" + ".join(api_args_sizes),
),
file=f_client,
)
print(dispatch_case_fmt.format(id=api_id, cdecl=api_decl),
file=f_server,
)
for i, (arg, ty) in enumerate(zip(api_args_names, api_args_types)):
serialise_arg (ty, api_args_sizes, i, arg, f_client)
deserialise_arg (ty, api_args_sizes, i, f_server)
insert_switch_case_break (f_server)
bother_dispatcher (api_id, f_client)
switch_add_default (api_id, f_server)
if __name__ == "__main__": if __name__ == "__main__":
......