Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/sunrpc/xdrgen/subcmds/source.py
26292 views
1
#!/usr/bin/env python3
2
# ex: set filetype=python:
3
4
"""Translate an XDR specification into executable code that
5
can be compiled for the Linux kernel."""
6
7
import logging
8
9
from argparse import Namespace
10
from lark import logger
11
from lark.exceptions import UnexpectedInput
12
13
from generators.source_top import XdrSourceTopGenerator
14
from generators.enum import XdrEnumGenerator
15
from generators.pointer import XdrPointerGenerator
16
from generators.program import XdrProgramGenerator
17
from generators.typedef import XdrTypedefGenerator
18
from generators.struct import XdrStructGenerator
19
from generators.union import XdrUnionGenerator
20
21
from xdr_ast import transform_parse_tree, _RpcProgram, Specification
22
from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer
23
from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion
24
25
from xdr_parse import xdr_parser, set_xdr_annotate
26
27
logger.setLevel(logging.INFO)
28
29
30
def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:
31
"""Emit one XDR decoder function for a source file"""
32
if isinstance(node, _XdrEnum):
33
gen = XdrEnumGenerator(language, peer)
34
elif isinstance(node, _XdrPointer):
35
gen = XdrPointerGenerator(language, peer)
36
elif isinstance(node, _XdrTypedef):
37
gen = XdrTypedefGenerator(language, peer)
38
elif isinstance(node, _XdrStruct):
39
gen = XdrStructGenerator(language, peer)
40
elif isinstance(node, _XdrUnion):
41
gen = XdrUnionGenerator(language, peer)
42
elif isinstance(node, _RpcProgram):
43
gen = XdrProgramGenerator(language, peer)
44
else:
45
return
46
gen.emit_decoder(node)
47
48
49
def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:
50
"""Emit one XDR encoder function for a source file"""
51
if isinstance(node, _XdrEnum):
52
gen = XdrEnumGenerator(language, peer)
53
elif isinstance(node, _XdrPointer):
54
gen = XdrPointerGenerator(language, peer)
55
elif isinstance(node, _XdrTypedef):
56
gen = XdrTypedefGenerator(language, peer)
57
elif isinstance(node, _XdrStruct):
58
gen = XdrStructGenerator(language, peer)
59
elif isinstance(node, _XdrUnion):
60
gen = XdrUnionGenerator(language, peer)
61
elif isinstance(node, _RpcProgram):
62
gen = XdrProgramGenerator(language, peer)
63
else:
64
return
65
gen.emit_encoder(node)
66
67
68
def generate_server_source(filename: str, root: Specification, language: str) -> None:
69
"""Generate server-side source code"""
70
71
gen = XdrSourceTopGenerator(language, "server")
72
gen.emit_source(filename, root)
73
74
for definition in root.definitions:
75
emit_source_decoder(definition.value, language, "server")
76
for definition in root.definitions:
77
emit_source_encoder(definition.value, language, "server")
78
79
80
def generate_client_source(filename: str, root: Specification, language: str) -> None:
81
"""Generate server-side source code"""
82
83
gen = XdrSourceTopGenerator(language, "client")
84
gen.emit_source(filename, root)
85
86
print("")
87
for definition in root.definitions:
88
emit_source_encoder(definition.value, language, "client")
89
for definition in root.definitions:
90
emit_source_decoder(definition.value, language, "client")
91
92
# cel: todo: client needs PROC macros
93
94
95
def handle_parse_error(e: UnexpectedInput) -> bool:
96
"""Simple parse error reporting, no recovery attempted"""
97
print(e)
98
return True
99
100
101
def subcmd(args: Namespace) -> int:
102
"""Generate encoder and decoder functions"""
103
104
set_xdr_annotate(args.annotate)
105
parser = xdr_parser()
106
with open(args.filename, encoding="utf-8") as f:
107
parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
108
ast = transform_parse_tree(parse_tree)
109
match args.peer:
110
case "server":
111
generate_server_source(args.filename, ast, args.language)
112
case "client":
113
generate_client_source(args.filename, ast, args.language)
114
case _:
115
print("Code generation for", args.peer, "is not yet supported")
116
117
return 0
118
119