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 VisitError 12 13from generators.enum import XdrEnumGenerator 14from generators.header_bottom import XdrHeaderBottomGenerator 15from generators.header_top import XdrHeaderTopGenerator 16from generators.pointer import XdrPointerGenerator 17from generators.program import XdrProgramGenerator 18from generators.typedef import XdrTypedefGenerator 19from generators.struct import XdrStructGenerator 20from generators.union import XdrUnionGenerator 21 22from xdr_ast import transform_parse_tree, _RpcProgram, Specification 23from xdr_ast import _XdrEnum, _XdrPointer, _XdrTypedef, _XdrStruct, _XdrUnion 24from xdr_ast import XdrSemanticError 25from xdr_parse import xdr_parser, set_xdr_annotate 26from xdr_parse import make_error_handler, XdrParseError 27from xdr_parse import handle_transform_error, handle_semantic_error 28 29logger.setLevel(logging.INFO) 30 31 32def emit_header_declarations(root: Specification, language: str, peer: str) -> None: 33 """Emit header declarations""" 34 for definition in root.definitions: 35 if isinstance(definition.value, _XdrEnum): 36 gen = XdrEnumGenerator(language, peer) 37 elif isinstance(definition.value, _XdrPointer): 38 gen = XdrPointerGenerator(language, peer) 39 elif isinstance(definition.value, _XdrTypedef): 40 gen = XdrTypedefGenerator(language, peer) 41 elif isinstance(definition.value, _XdrStruct): 42 gen = XdrStructGenerator(language, peer) 43 elif isinstance(definition.value, _XdrUnion): 44 gen = XdrUnionGenerator(language, peer) 45 elif isinstance(definition.value, _RpcProgram): 46 gen = XdrProgramGenerator(language, peer) 47 else: 48 continue 49 gen.emit_declaration(definition.value) 50 51 52def subcmd(args: Namespace) -> int: 53 """Generate definitions and declarations""" 54 55 set_xdr_annotate(args.annotate) 56 parser = xdr_parser() 57 with open(args.filename, encoding="utf-8") as f: 58 source = f.read() 59 try: 60 parse_tree = parser.parse( 61 source, on_error=make_error_handler(source, args.filename) 62 ) 63 except XdrParseError: 64 return 1 65 try: 66 ast = transform_parse_tree(parse_tree) 67 except VisitError as e: 68 handle_transform_error(e, source, args.filename) 69 return 1 70 except XdrSemanticError as e: 71 handle_semantic_error(e, source, args.filename) 72 return 1 73 74 gen = XdrHeaderTopGenerator(args.language, args.peer) 75 gen.emit_declaration(args.filename, ast) 76 77 emit_header_declarations(ast, args.language, args.peer) 78 79 gen = XdrHeaderBottomGenerator(args.language, args.peer) 80 gen.emit_declaration(args.filename, ast) 81 82 return 0 83