|
| 1 | +#!/usr/bin/env python |
| 2 | +# |
| 3 | +# ===- Generate headers for libc functions -------------------*- python -*--==# |
| 4 | +# |
| 5 | +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 6 | +# See https://llvm.org/LICENSE.txt for license information. |
| 7 | +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 8 | +# |
| 9 | +# ==-------------------------------------------------------------------------==# |
| 10 | + |
| 11 | + |
| 12 | +import yaml |
| 13 | +import re |
| 14 | +import argparse |
| 15 | + |
| 16 | +from pathlib import Path |
| 17 | +from header import HeaderFile |
| 18 | +from class_implementation.classes.macro import Macro |
| 19 | +from class_implementation.classes.type import Type |
| 20 | +from class_implementation.classes.function import Function |
| 21 | +from class_implementation.classes.include import Include |
| 22 | +from class_implementation.classes.enumeration import Enumeration |
| 23 | +from class_implementation.classes.object import Object |
| 24 | + |
| 25 | + |
| 26 | +def yaml_to_classes(yaml_data): |
| 27 | + """ |
| 28 | + Convert YAML data to header classes. |
| 29 | +
|
| 30 | + Args: |
| 31 | + yaml_data: The YAML data containing header specifications. |
| 32 | +
|
| 33 | + Returns: |
| 34 | + HeaderFile: An instance of HeaderFile populated with the data. |
| 35 | + """ |
| 36 | + header_name = yaml_data.get("header") |
| 37 | + header = HeaderFile(header_name) |
| 38 | + |
| 39 | + for macro_data in yaml_data.get("macros", []): |
| 40 | + header.add_macro(Macro(macro_data["macro_name"], macro_data["macro_value"])) |
| 41 | + |
| 42 | + for type_data in yaml_data.get("types", []): |
| 43 | + header.add_type(Type(type_data["type_name"])) |
| 44 | + |
| 45 | + for enum_data in yaml_data.get("enums", []): |
| 46 | + header.add_enumeration( |
| 47 | + Enumeration(enum_data["name"], enum_data.get("value", None)) |
| 48 | + ) |
| 49 | + |
| 50 | + for object_data in yaml_data.get("objects", []): |
| 51 | + header.add_object( |
| 52 | + Object(object_data["object_name"], object_data["object_type"]) |
| 53 | + ) |
| 54 | + |
| 55 | + for function_data in yaml_data.get("functions", []): |
| 56 | + arguments = [arg["type"] for arg in function_data["arguments"]] |
| 57 | + header.add_function( |
| 58 | + Function( |
| 59 | + function_data["return_type"], |
| 60 | + function_data["name"], |
| 61 | + arguments, |
| 62 | + function_data.get("guard"), |
| 63 | + function_data.get("attributes", []), |
| 64 | + ) |
| 65 | + ) |
| 66 | + |
| 67 | + for include_data in yaml_data.get("includes", []): |
| 68 | + header.add_include(Include(include_data)) |
| 69 | + |
| 70 | + return header |
| 71 | + |
| 72 | + |
| 73 | +def load_yaml_file(yaml_file): |
| 74 | + """ |
| 75 | + Load YAML file and convert it to header classes. |
| 76 | +
|
| 77 | + Args: |
| 78 | + yaml_file: The path to the YAML file. |
| 79 | +
|
| 80 | + Returns: |
| 81 | + HeaderFile: An instance of HeaderFile populated with the data from the YAML file. |
| 82 | + """ |
| 83 | + with open(yaml_file, "r") as f: |
| 84 | + yaml_data = yaml.safe_load(f) |
| 85 | + return yaml_to_classes(yaml_data) |
| 86 | + |
| 87 | + |
| 88 | +def fill_public_api(header_str, h_def_content): |
| 89 | + """ |
| 90 | + Replace the %%public_api() placeholder in the .h.def content with the generated header content. |
| 91 | +
|
| 92 | + Args: |
| 93 | + header_str: The generated header string. |
| 94 | + h_def_content: The content of the .h.def file. |
| 95 | +
|
| 96 | + Returns: |
| 97 | + The final header content with the public API filled in. |
| 98 | + """ |
| 99 | + return h_def_content.replace("%%public_api()", header_str, 1) |
| 100 | + |
| 101 | + |
| 102 | +def main(yaml_file, h_def_file, output_dir): |
| 103 | + """ |
| 104 | + Main function to generate header files from YAML and .h.def templates. |
| 105 | +
|
| 106 | + Args: |
| 107 | + yaml_file: Path to the YAML file containing header specification. |
| 108 | + h_def_file: Path to the .h.def template file. |
| 109 | + output_dir: Directory to output the generated header file. |
| 110 | + """ |
| 111 | + |
| 112 | + header = load_yaml_file(yaml_file) |
| 113 | + |
| 114 | + with open(h_def_file, "r") as f: |
| 115 | + h_def_content = f.read() |
| 116 | + |
| 117 | + header_str = str(header) |
| 118 | + final_header_content = fill_public_api(header_str, h_def_content) |
| 119 | + |
| 120 | + output_file_name = Path(h_def_file).stem |
| 121 | + output_file_path = Path(output_dir) / output_file_name |
| 122 | + |
| 123 | + with open(output_file_path, "w") as f: |
| 124 | + f.write(final_header_content) |
| 125 | + |
| 126 | + print(f"Generated header file: {output_file_path}") |
| 127 | + |
| 128 | + |
| 129 | +if __name__ == "__main__": |
| 130 | + parser = argparse.ArgumentParser( |
| 131 | + description="Generate header files from YAML and .h.def templates" |
| 132 | + ) |
| 133 | + parser.add_argument( |
| 134 | + "yaml_file", help="Path to the YAML file containing header specification" |
| 135 | + ) |
| 136 | + parser.add_argument("h_def_file", help="Path to the .h.def template file") |
| 137 | + parser.add_argument( |
| 138 | + "--output_dir", |
| 139 | + default=".", |
| 140 | + help="Directory to output the generated header file", |
| 141 | + ) |
| 142 | + args = parser.parse_args() |
| 143 | + |
| 144 | + main(args.yaml_file, args.h_def_file, args.output_dir) |
0 commit comments