| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #!/usr/bin/env python3
- # ex: set filetype=python:
- """Translate an XDR specification into executable code that
- can be compiled for the Linux kernel."""
- import logging
- from argparse import Namespace
- from lark import logger
- from lark.exceptions import VisitError
- from generators.source_top import XdrSourceTopGenerator
- from generators.enum import XdrEnumGenerator
- from generators.passthru import XdrPassthruGenerator
- from generators.pointer import XdrPointerGenerator
- from generators.program import XdrProgramGenerator
- from generators.typedef import XdrTypedefGenerator
- from generators.struct import XdrStructGenerator
- from generators.union import XdrUnionGenerator
- from xdr_ast import transform_parse_tree, _RpcProgram, Specification
- from xdr_ast import _XdrAst, _XdrEnum, _XdrPassthru, _XdrPointer
- from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion
- from xdr_parse import xdr_parser, set_xdr_annotate, set_xdr_enum_validation
- from xdr_parse import make_error_handler, XdrParseError
- from xdr_parse import handle_transform_error
- logger.setLevel(logging.INFO)
- def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:
- """Emit one XDR decoder function for a source file"""
- if isinstance(node, _XdrEnum):
- gen = XdrEnumGenerator(language, peer)
- elif isinstance(node, _XdrPointer):
- gen = XdrPointerGenerator(language, peer)
- elif isinstance(node, _XdrTypedef):
- gen = XdrTypedefGenerator(language, peer)
- elif isinstance(node, _XdrStruct):
- gen = XdrStructGenerator(language, peer)
- elif isinstance(node, _XdrUnion):
- gen = XdrUnionGenerator(language, peer)
- elif isinstance(node, _RpcProgram):
- gen = XdrProgramGenerator(language, peer)
- else:
- return
- gen.emit_decoder(node)
- def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:
- """Emit one XDR encoder function for a source file"""
- if isinstance(node, _XdrEnum):
- gen = XdrEnumGenerator(language, peer)
- elif isinstance(node, _XdrPointer):
- gen = XdrPointerGenerator(language, peer)
- elif isinstance(node, _XdrTypedef):
- gen = XdrTypedefGenerator(language, peer)
- elif isinstance(node, _XdrStruct):
- gen = XdrStructGenerator(language, peer)
- elif isinstance(node, _XdrUnion):
- gen = XdrUnionGenerator(language, peer)
- elif isinstance(node, _RpcProgram):
- gen = XdrProgramGenerator(language, peer)
- else:
- return
- gen.emit_encoder(node)
- def generate_server_source(filename: str, root: Specification, language: str) -> None:
- """Generate server-side source code"""
- gen = XdrSourceTopGenerator(language, "server")
- gen.emit_source(filename, root)
- for definition in root.definitions:
- if isinstance(definition.value, _XdrPassthru):
- passthru_gen = XdrPassthruGenerator(language, "server")
- passthru_gen.emit_decoder(definition.value)
- else:
- emit_source_decoder(definition.value, language, "server")
- for definition in root.definitions:
- if not isinstance(definition.value, _XdrPassthru):
- emit_source_encoder(definition.value, language, "server")
- def generate_client_source(filename: str, root: Specification, language: str) -> None:
- """Generate client-side source code"""
- gen = XdrSourceTopGenerator(language, "client")
- gen.emit_source(filename, root)
- for definition in root.definitions:
- if isinstance(definition.value, _XdrPassthru):
- passthru_gen = XdrPassthruGenerator(language, "client")
- passthru_gen.emit_decoder(definition.value)
- else:
- emit_source_encoder(definition.value, language, "client")
- for definition in root.definitions:
- if not isinstance(definition.value, _XdrPassthru):
- emit_source_decoder(definition.value, language, "client")
- # cel: todo: client needs PROC macros
- def subcmd(args: Namespace) -> int:
- """Generate encoder and decoder functions"""
- set_xdr_annotate(args.annotate)
- set_xdr_enum_validation(not args.no_enum_validation)
- parser = xdr_parser()
- with open(args.filename, encoding="utf-8") as f:
- source = f.read()
- try:
- parse_tree = parser.parse(
- source, on_error=make_error_handler(source, args.filename)
- )
- except XdrParseError:
- return 1
- try:
- ast = transform_parse_tree(parse_tree)
- except VisitError as e:
- handle_transform_error(e, source, args.filename)
- return 1
- match args.peer:
- case "server":
- generate_server_source(args.filename, ast, args.language)
- case "client":
- generate_client_source(args.filename, ast, args.language)
- case _:
- print("Code generation for", args.peer, "is not yet supported")
- return 0
|