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