Path: blob/master/tools/net/sunrpc/xdrgen/subcmds/source.py
26292 views
#!/usr/bin/env python31# ex: set filetype=python:23"""Translate an XDR specification into executable code that4can be compiled for the Linux kernel."""56import logging78from argparse import Namespace9from lark import logger10from lark.exceptions import UnexpectedInput1112from generators.source_top import XdrSourceTopGenerator13from generators.enum import XdrEnumGenerator14from generators.pointer import XdrPointerGenerator15from generators.program import XdrProgramGenerator16from generators.typedef import XdrTypedefGenerator17from generators.struct import XdrStructGenerator18from generators.union import XdrUnionGenerator1920from xdr_ast import transform_parse_tree, _RpcProgram, Specification21from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer22from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion2324from xdr_parse import xdr_parser, set_xdr_annotate2526logger.setLevel(logging.INFO)272829def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:30"""Emit one XDR decoder function for a source file"""31if isinstance(node, _XdrEnum):32gen = XdrEnumGenerator(language, peer)33elif isinstance(node, _XdrPointer):34gen = XdrPointerGenerator(language, peer)35elif isinstance(node, _XdrTypedef):36gen = XdrTypedefGenerator(language, peer)37elif isinstance(node, _XdrStruct):38gen = XdrStructGenerator(language, peer)39elif isinstance(node, _XdrUnion):40gen = XdrUnionGenerator(language, peer)41elif isinstance(node, _RpcProgram):42gen = XdrProgramGenerator(language, peer)43else:44return45gen.emit_decoder(node)464748def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:49"""Emit one XDR encoder function for a source file"""50if isinstance(node, _XdrEnum):51gen = XdrEnumGenerator(language, peer)52elif isinstance(node, _XdrPointer):53gen = XdrPointerGenerator(language, peer)54elif isinstance(node, _XdrTypedef):55gen = XdrTypedefGenerator(language, peer)56elif isinstance(node, _XdrStruct):57gen = XdrStructGenerator(language, peer)58elif isinstance(node, _XdrUnion):59gen = XdrUnionGenerator(language, peer)60elif isinstance(node, _RpcProgram):61gen = XdrProgramGenerator(language, peer)62else:63return64gen.emit_encoder(node)656667def generate_server_source(filename: str, root: Specification, language: str) -> None:68"""Generate server-side source code"""6970gen = XdrSourceTopGenerator(language, "server")71gen.emit_source(filename, root)7273for definition in root.definitions:74emit_source_decoder(definition.value, language, "server")75for definition in root.definitions:76emit_source_encoder(definition.value, language, "server")777879def generate_client_source(filename: str, root: Specification, language: str) -> None:80"""Generate server-side source code"""8182gen = XdrSourceTopGenerator(language, "client")83gen.emit_source(filename, root)8485print("")86for definition in root.definitions:87emit_source_encoder(definition.value, language, "client")88for definition in root.definitions:89emit_source_decoder(definition.value, language, "client")9091# cel: todo: client needs PROC macros929394def handle_parse_error(e: UnexpectedInput) -> bool:95"""Simple parse error reporting, no recovery attempted"""96print(e)97return True9899100def subcmd(args: Namespace) -> int:101"""Generate encoder and decoder functions"""102103set_xdr_annotate(args.annotate)104parser = xdr_parser()105with open(args.filename, encoding="utf-8") as f:106parse_tree = parser.parse(f.read(), on_error=handle_parse_error)107ast = transform_parse_tree(parse_tree)108match args.peer:109case "server":110generate_server_source(args.filename, ast, args.language)111case "client":112generate_client_source(args.filename, ast, args.language)113case _:114print("Code generation for", args.peer, "is not yet supported")115116return 0117118119