File Index
Files and directories
Sign in
FILE

source.py

File preview with syntax highlighting.

linux-6.19.14/tools/net/sunrpc/xdrgen/subcmds/source.py PYTHON
  1#!/usr/bin/env python3
  2# ex: set filetype=python:
  3
  4"""Translate an XDR specification into executable code that
  5can be compiled for the Linux kernel."""
  6
  7import logging
  8
  9from argparse import Namespace
 10from lark import logger
 11from lark.exceptions import UnexpectedInput
 12
 13from generators.source_top import XdrSourceTopGenerator
 14from generators.enum import XdrEnumGenerator
 15from generators.pointer import XdrPointerGenerator
 16from generators.program import XdrProgramGenerator
 17from generators.typedef import XdrTypedefGenerator
 18from generators.struct import XdrStructGenerator
 19from generators.union import XdrUnionGenerator
 20
 21from xdr_ast import transform_parse_tree, _RpcProgram, Specification
 22from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer
 23from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion
 24
 25from xdr_parse import xdr_parser, set_xdr_annotate
 26
 27logger.setLevel(logging.INFO)
 28
 29
 30def 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
 49def 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
 68def 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
 80def 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
 95def handle_parse_error(e: UnexpectedInput) -> bool:
 96    """Simple parse error reporting, no recovery attempted"""
 97    print(e)
 98    return True
 99
100
101def 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
~/ Read-only file preview.