1 # SPDX-License-Identifier: GPL-2.0
3 """Define a base code generator class"""
6 from jinja2
import Environment
, FileSystemLoader
, Template
8 from xdr_ast
import _XdrAst
, Specification
, _RpcProgram
, _XdrTypeSpecifier
9 from xdr_ast
import public_apis
, pass_by_reference
, get_header_name
10 from xdr_parse
import get_xdr_annotate
13 def create_jinja2_environment(language
: str, xdr_type
: str) -> Environment
:
14 """Open a set of templates based on output language"""
17 environment
= Environment(
18 loader
=FileSystemLoader(sys
.path
[0] + "/templates/C/" + xdr_type
+ "/"),
22 environment
.globals["annotate"] = get_xdr_annotate()
23 environment
.globals["public_apis"] = public_apis
24 environment
.globals["pass_by_reference"] = pass_by_reference
27 raise NotImplementedError("Language not supported")
30 def get_jinja2_template(
31 environment
: Environment
, template_type
: str, template_name
: str
33 """Retrieve a Jinja2 template for emitting source code"""
34 return environment
.get_template(template_type
+ "/" + template_name
+ ".j2")
37 def 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")
49 def 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()
56 def kernel_c_type(spec
: _XdrTypeSpecifier
) -> str:
57 """Return name of C type"""
58 builtin_native_c_type
= {
61 "unsigned_int": "u32",
63 "unsigned_long": "u32",
65 "unsigned_hyper": "u64",
67 if spec
.type_name
in builtin_native_c_type
:
68 return builtin_native_c_type
[spec
.type_name
]
73 """Base class to generate boilerplate for source files"""
75 def __init__(self
, language
: str, peer
: str):
76 """Initialize an instance of this class"""
77 raise NotImplementedError("No language support defined")
79 def emit_declaration(self
, filename
: str, root
: Specification
) -> None:
80 """Emit declaration header boilerplate"""
81 raise NotImplementedError("Header boilerplate generation not supported")
83 def emit_definition(self
, filename
: str, root
: Specification
) -> None:
84 """Emit definition header boilerplate"""
85 raise NotImplementedError("Header boilerplate generation not supported")
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")
92 class SourceGenerator
:
93 """Base class to generate header and source code for XDR types"""
95 def __init__(self
, language
: str, peer
: str):
96 """Initialize an instance of this class"""
97 raise NotImplementedError("No language support defined")
99 def emit_declaration(self
, node
: _XdrAst
) -> None:
100 """Emit one function declaration for this XDR type"""
101 raise NotImplementedError("Declaration generation not supported")
103 def emit_decoder(self
, node
: _XdrAst
) -> None:
104 """Emit one decoder function for this XDR type"""
105 raise NotImplementedError("Decoder generation not supported")
107 def emit_definition(self
, node
: _XdrAst
) -> None:
108 """Emit one definition for this XDR type"""
109 raise NotImplementedError("Definition generation not supported")
111 def emit_encoder(self
, node
: _XdrAst
) -> None:
112 """Emit one encoder function for this XDR type"""
113 raise NotImplementedError("Encoder generation not supported")
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")