brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 00c04ad Raw
119 lines · python
1#!/usr/bin/env python32# ex: set filetype=python:3 4"""Translate an XDR specification into executable code that5can be compiled for the Linux kernel."""6 7import logging8 9from argparse import Namespace10from lark import logger11from lark.exceptions import UnexpectedInput12 13from generators.source_top import XdrSourceTopGenerator14from generators.enum import XdrEnumGenerator15from generators.pointer import XdrPointerGenerator16from generators.program import XdrProgramGenerator17from generators.typedef import XdrTypedefGenerator18from generators.struct import XdrStructGenerator19from generators.union import XdrUnionGenerator20 21from xdr_ast import transform_parse_tree, _RpcProgram, Specification22from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer23from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion24 25from xdr_parse import xdr_parser, set_xdr_annotate26 27logger.setLevel(logging.INFO)28 29 30def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:31    """Emit one XDR decoder function for a source file"""32    if isinstance(node, _XdrEnum):33        gen = XdrEnumGenerator(language, peer)34    elif isinstance(node, _XdrPointer):35        gen = XdrPointerGenerator(language, peer)36    elif isinstance(node, _XdrTypedef):37        gen = XdrTypedefGenerator(language, peer)38    elif isinstance(node, _XdrStruct):39        gen = XdrStructGenerator(language, peer)40    elif isinstance(node, _XdrUnion):41        gen = XdrUnionGenerator(language, peer)42    elif isinstance(node, _RpcProgram):43        gen = XdrProgramGenerator(language, peer)44    else:45        return46    gen.emit_decoder(node)47 48 49def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:50    """Emit one XDR encoder function for a source file"""51    if isinstance(node, _XdrEnum):52        gen = XdrEnumGenerator(language, peer)53    elif isinstance(node, _XdrPointer):54        gen = XdrPointerGenerator(language, peer)55    elif isinstance(node, _XdrTypedef):56        gen = XdrTypedefGenerator(language, peer)57    elif isinstance(node, _XdrStruct):58        gen = XdrStructGenerator(language, peer)59    elif isinstance(node, _XdrUnion):60        gen = XdrUnionGenerator(language, peer)61    elif isinstance(node, _RpcProgram):62        gen = XdrProgramGenerator(language, peer)63    else:64        return65    gen.emit_encoder(node)66 67 68def generate_server_source(filename: str, root: Specification, language: str) -> None:69    """Generate server-side source code"""70 71    gen = XdrSourceTopGenerator(language, "server")72    gen.emit_source(filename, root)73 74    for definition in root.definitions:75        emit_source_decoder(definition.value, language, "server")76    for definition in root.definitions:77        emit_source_encoder(definition.value, language, "server")78 79 80def generate_client_source(filename: str, root: Specification, language: str) -> None:81    """Generate server-side source code"""82 83    gen = XdrSourceTopGenerator(language, "client")84    gen.emit_source(filename, root)85 86    # cel: todo: client needs XDR size macros87 88    for definition in root.definitions:89        emit_source_encoder(definition.value, language, "client")90    for definition in root.definitions:91        emit_source_decoder(definition.value, language, "client")92 93    # cel: todo: client needs PROC macros94 95 96def handle_parse_error(e: UnexpectedInput) -> bool:97    """Simple parse error reporting, no recovery attempted"""98    print(e)99    return True100 101 102def subcmd(args: Namespace) -> int:103    """Generate encoder and decoder functions"""104 105    set_xdr_annotate(args.annotate)106    parser = xdr_parser()107    with open(args.filename, encoding="utf-8") as f:108        parse_tree = parser.parse(f.read(), on_error=handle_parse_error)109        ast = transform_parse_tree(parse_tree)110        match args.peer:111            case "server":112                generate_server_source(args.filename, ast, args.language)113            case "client":114                generate_client_source(args.filename, ast, args.language)115            case _:116                print("Code generation for", args.peer, "is not yet supported")117 118    return 0119