scanner: drop the Target class, push to templates

The Target was specific to libei/libeis, it resolved to "ei" or
"eis_client" depending on which component we were building. But that's
specific to our C implementation here, so let's push it into our C
implementation templates.
This commit is contained in:
Peter Hutterer 2023-02-16 09:17:17 +10:00
parent e0d0c1af61
commit 29cf354de6
3 changed files with 34 additions and 42 deletions

View file

@ -7,9 +7,6 @@
{#- this is a jinja template, warning above is for the generated file
Non-obvious variables set by the scanner that are used in this template:
- target: because eis is actually eis_client in the code, the target points to
either "ei" or "eis_client". The various attributes on target resolve
accordingly.
- request.fqdn/event.fqdn - the full name of a request/event with the
interface name prefixed, "ei_foo_request_bar" or "ei_foo_event_bar"
- incoming/outgoing: points to the list of requests or events, depending
@ -17,6 +14,16 @@
generating (ei or eis)
#}
{# target: because eis is actually eis_client in the code, the target points to
either "ei" or "eis_client" and we need the matching get_context or
get_client for those. This is specific to the libei/libeis implementation
so it's done here in the template only. #}
{% set target = {} %}
{% if component == "eis" %}
{% set target = { "name": "eis_client", "context": "client" } %}
{% else %}
{% set target = { "name": "ei", "context": "context" } %}
{% endif %}
#include <assert.h>
#include <errno.h>
@ -39,7 +46,7 @@ struct {{target.name}};
* message sending functions (requests for libei, events for libeis).
*/
extern int {{target.name}}_send_message(
{{target.as_arg}}, const struct brei_object *obj, uint32_t opcode,
{{target.name|as_arg}}, const struct brei_object *obj, uint32_t opcode,
const char *signature, size_t nargs, ...
);
@ -52,7 +59,7 @@ extern int {{target.name}}_send_message(
const struct {{interface.name}}_interface *{{interface.name}}_get_interface({{interface.as_arg}});
/* returns the message sending context from the given struct */
{{target.ctype}} {{interface.name}}_get_{{target.context}}({{interface.as_arg}});
{{target.name|ctype}} {{interface.name}}_get_{{target.context}}({{interface.as_arg}});
/* Returns the protocol object id from the given struct */
const struct brei_object *
@ -77,7 +84,7 @@ int
return -ENOENT;
const struct brei_object *obj = {{interface.name}}_get_proto_object({{interface.name}});
{{target.ctype}} ctx = {{interface.name}}_get_{{target.context}}({{interface.name}});
{{target.name|ctype}} ctx = {{interface.name}}_get_{{target.context}}({{interface.name}});
if (obj->version < {{outgoing.fqdn.upper()}}_SINCE_VERSION)
return -ENOTSUP;

View file

@ -7,8 +7,6 @@
{# this is a jinja template, warning above is for the generated file
Non-obvious variables set by the scanner that are used in this template:
- target: because eis is actually eis_client in the code, the target points to
either "ei" or "eis_client"
- request.fqdn/event.fqdn - the full name of a request/event with the
interface name prefixed, "ei_foo_request_bar" or "ei_foo_event_bar"
- incoming/outgoing: points to the list of requests or events, depending
@ -16,6 +14,16 @@
generating (ei or eis)
#}
{# target: because eis is actually eis_client in the code, the target points to
either "ei" or "eis_client" and we need the matching get_context or
get_client for those. This is specific to the libei/libeis implementation
so it's done here in the template only. #}
{% if component == "eis" %}
{% set target = { "name": "eis_client", "context": "client" } %}
{% else %}
{% set target = { "name": "ei", "context": "context" } %}
{% endif %}
#pragma once
#ifdef _cplusplus

View file

@ -36,35 +36,6 @@ def proto_to_type(proto: str) -> Optional[str]:
}.get(proto)
@attr.s
class Target:
"""
Defines the target struct for the base "ei" interface.
In libei we have a `struct ei` but in libeis the equivalent
level is `struct eis_client`. This target type maps those two.
"""
name: str = attr.ib()
context: str = attr.ib()
@property
def ctype(self) -> str:
return f"struct {self.name} *"
@property
def as_param(self) -> str:
return f"struct {self.name}* {self.name}"
@property
def as_arg(self) -> str:
return self.as_param
@classmethod
def create(cls, name: str, context: str) -> "Target":
return cls(name=name, context=context)
@attr.s
class Argument:
"""
@ -599,14 +570,9 @@ def generate_source(
proto: Protocol, headerfile: Optional[str], template: Path, component: str
) -> jinja2.environment.TemplateStream:
assert component in ["ei", "eis"]
target = {
"ei": Target.create("ei", context="context"),
"eis": Target.create("eis_client", context="client"),
}[component]
data = {}
data["component"] = component
data["target"] = target
data["interfaces"] = proto.interfaces
if headerfile:
data["headerfile"] = headerfile
@ -616,6 +582,17 @@ def generate_source(
trim_blocks=True,
lstrip_blocks=True,
)
# jinja filter to convert foo into "struct foo *"
def filter_ctype(name):
return f"struct {name} *"
# jinja filter to convert foo into "struct foo *foo"
def filter_as_arg(name):
return f"struct {name} * {name}"
env.filters["ctype"] = filter_ctype
env.filters["as_arg"] = filter_as_arg
jtemplate = env.get_template(template.name)
return jtemplate.stream(data)