Skip to content

Commit a917d48

Browse files
aaryanshuklaAlexisPerry
authored andcommitted
[libc] added newhdrgen python script and class file (llvm#96671)
python script uses yaml and classes to generate c headers header.py is only the main class file, the rest will be in another pr more files to be added in multiple prs
1 parent ffa6ffd commit a917d48

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

libc/newhdrgen/header.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python
2+
#
3+
# ====- HeaderFile Class for libc function headers -----------*- 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+
class HeaderFile:
13+
def __init__(self, name):
14+
self.name = name
15+
self.macros = []
16+
self.types = []
17+
self.enumerations = []
18+
self.objects = []
19+
self.functions = []
20+
self.includes = []
21+
22+
def add_macro(self, macro):
23+
self.macros.append(macro)
24+
25+
def add_type(self, type_):
26+
self.types.append(type_)
27+
28+
def add_enumeration(self, enumeration):
29+
self.enumerations.append(enumeration)
30+
31+
def add_object(self, object):
32+
self.objects.append(object)
33+
34+
def add_function(self, function):
35+
self.functions.append(function)
36+
37+
def add_include(self, include):
38+
self.includes.append(include)
39+
40+
def __str__(self):
41+
content = [""]
42+
43+
for include in self.includes:
44+
content.append(str(include))
45+
46+
for macro in self.macros:
47+
content.append(str(macro))
48+
49+
for object in self.objects:
50+
content.append(str(object))
51+
52+
for type_ in self.types:
53+
content.append(str(type_))
54+
55+
if self.enumerations:
56+
content.append("enum {")
57+
for enum in self.enumerations:
58+
content.append(f"\t{str(enum)},")
59+
content.append("};")
60+
61+
# TODO: replace line below with common.h functionality
62+
content.append("__BEGIN_C_DECLS\n")
63+
for function in self.functions:
64+
content.append(str(function))
65+
content.append("")
66+
content.append("__END_C_DECLS\n")
67+
return "\n".join(content)

libc/newhdrgen/yaml_to_classes.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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

Comments
 (0)