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