1# SPDX-License-Identifier: GPL-2.0 2 3"""Define a base code generator class""" 4 5from pathlib import Path 6from jinja2 import Environment, FileSystemLoader, Template 7 8from xdr_ast import _XdrAst, Specification, _RpcProgram, _XdrTypeSpecifier 9from xdr_ast import public_apis, pass_by_reference, structs, get_header_name 10from xdr_parse import get_xdr_annotate 11 12 13def create_jinja2_environment(language: str, xdr_type: str) -> Environment: 14 """Open a set of templates based on output language""" 15 match language: 16 case "C": 17 templates_dir = ( 18 Path(__file__).parent.parent / "templates" / language / xdr_type 19 ) 20 environment = Environment( 21 loader=FileSystemLoader(templates_dir), 22 trim_blocks=True, 23 lstrip_blocks=True, 24 ) 25 environment.globals["annotate"] = get_xdr_annotate() 26 environment.globals["public_apis"] = public_apis 27 environment.globals["pass_by_reference"] = pass_by_reference 28 environment.globals["structs"] = structs 29 return environment 30 case _: 31 raise NotImplementedError("Language not supported") 32 33 34def get_jinja2_template( 35 environment: Environment, template_type: str, template_name: str 36) -> Template: 37 """Retrieve a Jinja2 template for emitting source code""" 38 return environment.get_template(template_type + "/" + template_name + ".j2") 39 40 41def find_xdr_program_name(root: Specification) -> str: 42 """Retrieve the RPC program name from an abstract syntax tree""" 43 raw_name = get_header_name() 44 if raw_name != "none": 45 return raw_name.lower() 46 for definition in root.definitions: 47 if isinstance(definition.value, _RpcProgram): 48 raw_name = definition.value.name 49 return raw_name.lower().removesuffix("_program").removesuffix("_prog") 50 return "noprog" 51 52 53def header_guard_infix(filename: str) -> str: 54 """Extract the header guard infix from the specification filename""" 55 return Path(filename).stem.upper() 56 57 58def kernel_c_type(spec: _XdrTypeSpecifier) -> str: 59 """Return name of C type""" 60 builtin_native_c_type = { 61 "bool": "bool", 62 "int": "s32", 63 "unsigned_int": "u32", 64 "long": "s32", 65 "unsigned_long": "u32", 66 "hyper": "s64", 67 "unsigned_hyper": "u64", 68 } 69 if spec.type_name in builtin_native_c_type: 70 return builtin_native_c_type[spec.type_name] 71 return spec.type_name 72 73 74class Boilerplate: 75 """Base class to generate boilerplate for source files""" 76 77 def __init__(self, language: str, peer: str): 78 """Initialize an instance of this class""" 79 raise NotImplementedError("No language support defined") 80 81 def emit_declaration(self, filename: str, root: Specification) -> None: 82 """Emit declaration header boilerplate""" 83 raise NotImplementedError("Header boilerplate generation not supported") 84 85 def emit_definition(self, filename: str, root: Specification) -> None: 86 """Emit definition header boilerplate""" 87 raise NotImplementedError("Header boilerplate generation not supported") 88 89 def emit_source(self, filename: str, root: Specification) -> None: 90 """Emit generic source code for this XDR type""" 91 raise NotImplementedError("Source boilerplate generation not supported") 92 93 94class SourceGenerator: 95 """Base class to generate header and source code for XDR types""" 96 97 def __init__(self, language: str, peer: str): 98 """Initialize an instance of this class""" 99 raise NotImplementedError("No language support defined") 100 101 def emit_declaration(self, node: _XdrAst) -> None: 102 """Emit one function declaration for this XDR type""" 103 raise NotImplementedError("Declaration generation not supported") 104 105 def emit_decoder(self, node: _XdrAst) -> None: 106 """Emit one decoder function for this XDR type""" 107 raise NotImplementedError("Decoder generation not supported") 108 109 def emit_definition(self, node: _XdrAst) -> None: 110 """Emit one definition for this XDR type""" 111 raise NotImplementedError("Definition generation not supported") 112 113 def emit_encoder(self, node: _XdrAst) -> None: 114 """Emit one encoder function for this XDR type""" 115 raise NotImplementedError("Encoder generation not supported") 116 117 def emit_maxsize(self, node: _XdrAst) -> None: 118 """Emit one maxsize macro for this XDR type""" 119 raise NotImplementedError("Maxsize macro generation not supported") 120