Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/sunrpc/xdrgen/generators/union.py
26292 views
1
#!/usr/bin/env python3
2
# ex: set filetype=python:
3
4
"""Generate code to handle XDR unions"""
5
6
from jinja2 import Environment
7
8
from generators import SourceGenerator
9
from generators import create_jinja2_environment, get_jinja2_template
10
11
from xdr_ast import _XdrBasic, _XdrUnion, _XdrVoid, get_header_name
12
from xdr_ast import _XdrDeclaration, _XdrCaseSpec, public_apis, big_endian
13
14
15
def emit_union_declaration(environment: Environment, node: _XdrUnion) -> None:
16
"""Emit one declaration pair for an XDR union type"""
17
if node.name in public_apis:
18
template = get_jinja2_template(environment, "declaration", "close")
19
print(template.render(name=node.name))
20
21
22
def emit_union_switch_spec_definition(
23
environment: Environment, node: _XdrDeclaration
24
) -> None:
25
"""Emit a definition for an XDR union's discriminant"""
26
assert isinstance(node, _XdrBasic)
27
template = get_jinja2_template(environment, "definition", "switch_spec")
28
print(
29
template.render(
30
name=node.name,
31
type=node.spec.type_name,
32
classifier=node.spec.c_classifier,
33
)
34
)
35
36
37
def emit_union_case_spec_definition(
38
environment: Environment, node: _XdrDeclaration
39
) -> None:
40
"""Emit a definition for an XDR union's case arm"""
41
if isinstance(node.arm, _XdrVoid):
42
return
43
assert isinstance(node.arm, _XdrBasic)
44
template = get_jinja2_template(environment, "definition", "case_spec")
45
print(
46
template.render(
47
name=node.arm.name,
48
type=node.arm.spec.type_name,
49
classifier=node.arm.spec.c_classifier,
50
)
51
)
52
53
54
def emit_union_definition(environment: Environment, node: _XdrUnion) -> None:
55
"""Emit one XDR union definition"""
56
template = get_jinja2_template(environment, "definition", "open")
57
print(template.render(name=node.name))
58
59
emit_union_switch_spec_definition(environment, node.discriminant)
60
61
for case in node.cases:
62
emit_union_case_spec_definition(environment, case)
63
64
if node.default is not None:
65
emit_union_case_spec_definition(environment, node.default)
66
67
template = get_jinja2_template(environment, "definition", "close")
68
print(template.render(name=node.name))
69
70
71
def emit_union_switch_spec_decoder(
72
environment: Environment, node: _XdrDeclaration
73
) -> None:
74
"""Emit a decoder for an XDR union's discriminant"""
75
assert isinstance(node, _XdrBasic)
76
template = get_jinja2_template(environment, "decoder", "switch_spec")
77
print(template.render(name=node.name, type=node.spec.type_name))
78
79
80
def emit_union_case_spec_decoder(
81
environment: Environment, node: _XdrCaseSpec, big_endian_discriminant: bool
82
) -> None:
83
"""Emit decoder functions for an XDR union's case arm"""
84
85
if isinstance(node.arm, _XdrVoid):
86
return
87
88
if big_endian_discriminant:
89
template = get_jinja2_template(environment, "decoder", "case_spec_be")
90
else:
91
template = get_jinja2_template(environment, "decoder", "case_spec")
92
for case in node.values:
93
print(template.render(case=case))
94
95
assert isinstance(node.arm, _XdrBasic)
96
template = get_jinja2_template(environment, "decoder", node.arm.template)
97
print(
98
template.render(
99
name=node.arm.name,
100
type=node.arm.spec.type_name,
101
classifier=node.arm.spec.c_classifier,
102
)
103
)
104
105
template = get_jinja2_template(environment, "decoder", "break")
106
print(template.render())
107
108
109
def emit_union_default_spec_decoder(environment: Environment, node: _XdrUnion) -> None:
110
"""Emit a decoder function for an XDR union's default arm"""
111
default_case = node.default
112
113
# Avoid a gcc warning about a default case with boolean discriminant
114
if default_case is None and node.discriminant.spec.type_name == "bool":
115
return
116
117
template = get_jinja2_template(environment, "decoder", "default_spec")
118
print(template.render())
119
120
if default_case is None or isinstance(default_case.arm, _XdrVoid):
121
template = get_jinja2_template(environment, "decoder", "break")
122
print(template.render())
123
return
124
125
assert isinstance(default_case.arm, _XdrBasic)
126
template = get_jinja2_template(environment, "decoder", default_case.arm.template)
127
print(
128
template.render(
129
name=default_case.arm.name,
130
type=default_case.arm.spec.type_name,
131
classifier=default_case.arm.spec.c_classifier,
132
)
133
)
134
135
136
def emit_union_decoder(environment: Environment, node: _XdrUnion) -> None:
137
"""Emit one XDR union decoder"""
138
template = get_jinja2_template(environment, "decoder", "open")
139
print(template.render(name=node.name))
140
141
emit_union_switch_spec_decoder(environment, node.discriminant)
142
143
for case in node.cases:
144
emit_union_case_spec_decoder(
145
environment,
146
case,
147
node.discriminant.spec.type_name in big_endian,
148
)
149
150
emit_union_default_spec_decoder(environment, node)
151
152
template = get_jinja2_template(environment, "decoder", "close")
153
print(template.render())
154
155
156
def emit_union_switch_spec_encoder(
157
environment: Environment, node: _XdrDeclaration
158
) -> None:
159
"""Emit an encoder for an XDR union's discriminant"""
160
assert isinstance(node, _XdrBasic)
161
template = get_jinja2_template(environment, "encoder", "switch_spec")
162
print(template.render(name=node.name, type=node.spec.type_name))
163
164
165
def emit_union_case_spec_encoder(
166
environment: Environment, node: _XdrCaseSpec, big_endian_discriminant: bool
167
) -> None:
168
"""Emit encoder functions for an XDR union's case arm"""
169
170
if isinstance(node.arm, _XdrVoid):
171
return
172
173
if big_endian_discriminant:
174
template = get_jinja2_template(environment, "encoder", "case_spec_be")
175
else:
176
template = get_jinja2_template(environment, "encoder", "case_spec")
177
for case in node.values:
178
print(template.render(case=case))
179
180
template = get_jinja2_template(environment, "encoder", node.arm.template)
181
print(
182
template.render(
183
name=node.arm.name,
184
type=node.arm.spec.type_name,
185
)
186
)
187
188
template = get_jinja2_template(environment, "encoder", "break")
189
print(template.render())
190
191
192
def emit_union_default_spec_encoder(environment: Environment, node: _XdrUnion) -> None:
193
"""Emit an encoder function for an XDR union's default arm"""
194
default_case = node.default
195
196
# Avoid a gcc warning about a default case with boolean discriminant
197
if default_case is None and node.discriminant.spec.type_name == "bool":
198
return
199
200
template = get_jinja2_template(environment, "encoder", "default_spec")
201
print(template.render())
202
203
if default_case is None or isinstance(default_case.arm, _XdrVoid):
204
template = get_jinja2_template(environment, "encoder", "break")
205
print(template.render())
206
return
207
208
template = get_jinja2_template(environment, "encoder", default_case.arm.template)
209
print(
210
template.render(
211
name=default_case.arm.name,
212
type=default_case.arm.spec.type_name,
213
)
214
)
215
216
217
def emit_union_encoder(environment, node: _XdrUnion) -> None:
218
"""Emit one XDR union encoder"""
219
template = get_jinja2_template(environment, "encoder", "open")
220
print(template.render(name=node.name))
221
222
emit_union_switch_spec_encoder(environment, node.discriminant)
223
224
for case in node.cases:
225
emit_union_case_spec_encoder(
226
environment,
227
case,
228
node.discriminant.spec.type_name in big_endian,
229
)
230
231
emit_union_default_spec_encoder(environment, node)
232
233
template = get_jinja2_template(environment, "encoder", "close")
234
print(template.render())
235
236
237
def emit_union_maxsize(environment: Environment, node: _XdrUnion) -> None:
238
"""Emit one maxsize macro for an XDR union type"""
239
macro_name = get_header_name().upper() + "_" + node.name + "_sz"
240
template = get_jinja2_template(environment, "maxsize", "union")
241
print(
242
template.render(
243
macro=macro_name,
244
width=" + ".join(node.symbolic_width()),
245
)
246
)
247
248
249
class XdrUnionGenerator(SourceGenerator):
250
"""Generate source code for XDR unions"""
251
252
def __init__(self, language: str, peer: str):
253
"""Initialize an instance of this class"""
254
self.environment = create_jinja2_environment(language, "union")
255
self.peer = peer
256
257
def emit_declaration(self, node: _XdrUnion) -> None:
258
"""Emit one declaration pair for an XDR union"""
259
emit_union_declaration(self.environment, node)
260
261
def emit_definition(self, node: _XdrUnion) -> None:
262
"""Emit one definition for an XDR union"""
263
emit_union_definition(self.environment, node)
264
265
def emit_decoder(self, node: _XdrUnion) -> None:
266
"""Emit one decoder function for an XDR union"""
267
emit_union_decoder(self.environment, node)
268
269
def emit_encoder(self, node: _XdrUnion) -> None:
270
"""Emit one encoder function for an XDR union"""
271
emit_union_encoder(self.environment, node)
272
273
def emit_maxsize(self, node: _XdrUnion) -> None:
274
"""Emit one maxsize macro for an XDR union"""
275
emit_union_maxsize(self.environment, node)
276
277