1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
# SPDX-License-Identifier: GPL-2.0
"""Define a base code generator class"""
from pathlib import Path
from jinja2 import Environment, FileSystemLoader, Template
from xdr_ast import _XdrAst, Specification, _RpcProgram, _XdrTypeSpecifier
from xdr_ast import public_apis, pass_by_reference, structs, get_header_name
from xdr_parse import get_xdr_annotate
def create_jinja2_environment(language: str, xdr_type: str) -> Environment:
"""Open a set of templates based on output language"""
match language:
case "C":
templates_dir = (
Path(__file__).parent.parent / "templates" / language / xdr_type
)
environment = Environment(
loader=FileSystemLoader(templates_dir),
trim_blocks=True,
lstrip_blocks=True,
)
environment.globals["annotate"] = get_xdr_annotate()
environment.globals["public_apis"] = public_apis
environment.globals["pass_by_reference"] = pass_by_reference
environment.globals["structs"] = structs
return environment
case _:
raise NotImplementedError("Language not supported")
def get_jinja2_template(
environment: Environment, template_type: str, template_name: str
) -> Template:
"""Retrieve a Jinja2 template for emitting source code"""
return environment.get_template(template_type + "/" + template_name + ".j2")
def find_xdr_program_name(root: Specification) -> str:
"""Retrieve the RPC program name from an abstract syntax tree"""
raw_name = get_header_name()
if raw_name != "none":
return raw_name.lower()
for definition in root.definitions:
if isinstance(definition.value, _RpcProgram):
raw_name = definition.value.name
return raw_name.lower().removesuffix("_program").removesuffix("_prog")
return "noprog"
def header_guard_infix(filename: str) -> str:
"""Extract the header guard infix from the specification filename"""
return Path(filename).stem.upper()
def kernel_c_type(spec: _XdrTypeSpecifier) -> str:
"""Return name of C type"""
builtin_native_c_type = {
"bool": "bool",
"int": "s32",
"unsigned_int": "u32",
"long": "s32",
"unsigned_long": "u32",
"hyper": "s64",
"unsigned_hyper": "u64",
}
if spec.type_name in builtin_native_c_type:
return builtin_native_c_type[spec.type_name]
return spec.type_name
class Boilerplate:
"""Base class to generate boilerplate for source files"""
def __init__(self, language: str, peer: str):
"""Initialize an instance of this class"""
raise NotImplementedError("No language support defined")
def emit_declaration(self, filename: str, root: Specification) -> None:
"""Emit declaration header boilerplate"""
raise NotImplementedError("Header boilerplate generation not supported")
def emit_definition(self, filename: str, root: Specification) -> None:
"""Emit definition header boilerplate"""
raise NotImplementedError("Header boilerplate generation not supported")
def emit_source(self, filename: str, root: Specification) -> None:
"""Emit generic source code for this XDR type"""
raise NotImplementedError("Source boilerplate generation not supported")
class SourceGenerator:
"""Base class to generate header and source code for XDR types"""
def __init__(self, language: str, peer: str):
"""Initialize an instance of this class"""
raise NotImplementedError("No language support defined")
def emit_declaration(self, node: _XdrAst) -> None:
"""Emit one function declaration for this XDR type"""
raise NotImplementedError("Declaration generation not supported")
def emit_decoder(self, node: _XdrAst) -> None:
"""Emit one decoder function for this XDR type"""
raise NotImplementedError("Decoder generation not supported")
def emit_definition(self, node: _XdrAst) -> None:
"""Emit one definition for this XDR type"""
raise NotImplementedError("Definition generation not supported")
def emit_encoder(self, node: _XdrAst) -> None:
"""Emit one encoder function for this XDR type"""
raise NotImplementedError("Encoder generation not supported")
def emit_maxsize(self, node: _XdrAst) -> None:
"""Emit one maxsize macro for this XDR type"""
raise NotImplementedError("Maxsize macro generation not supported")
|