| #!/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.enum import XdrEnumGenerator | |
| from generators.header_bottom import XdrHeaderBottomGenerator | |
| from generators.header_top import XdrHeaderTopGenerator | |
| 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 _XdrEnum, _XdrPointer, _XdrTypedef, _XdrStruct, _XdrUnion | |
| from xdr_ast import XdrSemanticError | |
| from xdr_parse import xdr_parser, set_xdr_annotate | |
| from xdr_parse import make_error_handler, XdrParseError | |
| from xdr_parse import handle_transform_error, handle_semantic_error | |
| logger.setLevel(logging.INFO) | |
| def emit_header_declarations(root: Specification, language: str, peer: str) -> None: | |
| """Emit header declarations""" | |
| for definition in root.definitions: | |
| if isinstance(definition.value, _XdrEnum): | |
| gen = XdrEnumGenerator(language, peer) | |
| elif isinstance(definition.value, _XdrPointer): | |
| gen = XdrPointerGenerator(language, peer) | |
| elif isinstance(definition.value, _XdrTypedef): | |
| gen = XdrTypedefGenerator(language, peer) | |
| elif isinstance(definition.value, _XdrStruct): | |
| gen = XdrStructGenerator(language, peer) | |
| elif isinstance(definition.value, _XdrUnion): | |
| gen = XdrUnionGenerator(language, peer) | |
| elif isinstance(definition.value, _RpcProgram): | |
| gen = XdrProgramGenerator(language, peer) | |
| else: | |
| continue | |
| gen.emit_declaration(definition.value) | |
| def subcmd(args: Namespace) -> int: | |
| """Generate definitions and declarations""" | |
| set_xdr_annotate(args.annotate) | |
| 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 | |
| except XdrSemanticError as e: | |
| handle_semantic_error(e, source, args.filename) | |
| return 1 | |
| gen = XdrHeaderTopGenerator(args.language, args.peer) | |
| gen.emit_declaration(args.filename, ast) | |
| emit_header_declarations(ast, args.language, args.peer) | |
| gen = XdrHeaderBottomGenerator(args.language, args.peer) | |
| gen.emit_declaration(args.filename, ast) | |
| return 0 |