at master 107 lines 4.1 kB view raw
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.constant import XdrConstantGenerator 14from generators.enum import XdrEnumGenerator 15from generators.header_bottom import XdrHeaderBottomGenerator 16from generators.header_top import XdrHeaderTopGenerator 17from generators.passthru import XdrPassthruGenerator 18from generators.pointer import XdrPointerGenerator 19from generators.program import XdrProgramGenerator 20from generators.typedef import XdrTypedefGenerator 21from generators.struct import XdrStructGenerator 22from generators.union import XdrUnionGenerator 23 24from xdr_ast import transform_parse_tree, Specification 25from xdr_ast import _RpcProgram, _XdrConstant, _XdrEnum, _XdrPassthru, _XdrPointer 26from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion 27from xdr_parse import xdr_parser, set_xdr_annotate 28from xdr_parse import make_error_handler, XdrParseError 29from xdr_parse import handle_transform_error 30 31logger.setLevel(logging.INFO) 32 33 34def emit_header_definitions(root: Specification, language: str, peer: str) -> None: 35 """Emit header definitions""" 36 for definition in root.definitions: 37 if isinstance(definition.value, _XdrConstant): 38 gen = XdrConstantGenerator(language, peer) 39 elif isinstance(definition.value, _XdrEnum): 40 gen = XdrEnumGenerator(language, peer) 41 elif isinstance(definition.value, _XdrPointer): 42 gen = XdrPointerGenerator(language, peer) 43 elif isinstance(definition.value, _RpcProgram): 44 gen = XdrProgramGenerator(language, peer) 45 elif isinstance(definition.value, _XdrTypedef): 46 gen = XdrTypedefGenerator(language, peer) 47 elif isinstance(definition.value, _XdrStruct): 48 gen = XdrStructGenerator(language, peer) 49 elif isinstance(definition.value, _XdrUnion): 50 gen = XdrUnionGenerator(language, peer) 51 elif isinstance(definition.value, _XdrPassthru): 52 gen = XdrPassthruGenerator(language, peer) 53 else: 54 continue 55 gen.emit_definition(definition.value) 56 57 58def emit_header_maxsize(root: Specification, language: str, peer: str) -> None: 59 """Emit header maxsize macros""" 60 print("") 61 for definition in root.definitions: 62 if isinstance(definition.value, _XdrEnum): 63 gen = XdrEnumGenerator(language, peer) 64 elif isinstance(definition.value, _XdrPointer): 65 gen = XdrPointerGenerator(language, peer) 66 elif isinstance(definition.value, _XdrTypedef): 67 gen = XdrTypedefGenerator(language, peer) 68 elif isinstance(definition.value, _XdrStruct): 69 gen = XdrStructGenerator(language, peer) 70 elif isinstance(definition.value, _XdrUnion): 71 gen = XdrUnionGenerator(language, peer) 72 elif isinstance(definition.value, _RpcProgram): 73 gen = XdrProgramGenerator(language, peer) 74 else: 75 continue 76 gen.emit_maxsize(definition.value) 77 78 79def subcmd(args: Namespace) -> int: 80 """Generate definitions""" 81 82 set_xdr_annotate(args.annotate) 83 parser = xdr_parser() 84 with open(args.filename, encoding="utf-8") as f: 85 source = f.read() 86 try: 87 parse_tree = parser.parse( 88 source, on_error=make_error_handler(source, args.filename) 89 ) 90 except XdrParseError: 91 return 1 92 try: 93 ast = transform_parse_tree(parse_tree) 94 except VisitError as e: 95 handle_transform_error(e, source, args.filename) 96 return 1 97 98 gen = XdrHeaderTopGenerator(args.language, args.peer) 99 gen.emit_definition(args.filename, ast) 100 101 emit_header_definitions(ast, args.language, args.peer) 102 emit_header_maxsize(ast, args.language, args.peer) 103 104 gen = XdrHeaderBottomGenerator(args.language, args.peer) 105 gen.emit_definition(args.filename, ast) 106 107 return 0