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