]>
Commit | Line | Data |
---|---|---|
a2e28389 UD |
1 | #!/usr/bin/env python3 |
2 | ||
a945c346 | 3 | # Copyright (C) 2022-2024 Free Software Foundation, Inc. |
a2e28389 UD |
4 | # This file is part of GCC. |
5 | ||
6 | # GCC is free software; you can redistribute it and/or modify | |
7 | # it under the terms of the GNU General Public License as published by | |
8 | # the Free Software Foundation; either version 3, or (at your option) | |
9 | # any later version. | |
10 | ||
11 | # GCC is distributed in the hope that it will be useful, | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | # GNU General Public License for more details. | |
15 | ||
16 | # You should have received a copy of the GNU General Public License | |
17 | # along with GCC; see the file COPYING3. If not see | |
18 | # <http://www.gnu.org/licenses/>. | |
19 | ||
20 | ||
21 | # Generate gcc source files: | |
22 | # - the export description of the standard C++ library module | |
23 | # - the gperf tables used to hint at actions to fix problems | |
24 | # related to missing symbols in the std:: namespace | |
25 | ||
26 | import csv | |
27 | import os | |
28 | import time | |
29 | ||
30 | # The CSV file contains the following columns: | |
31 | # column value | |
32 | # 1 header file, including angle brackets | |
33 | # 2 symbol name without std:: prefix | |
34 | # 3 nonzero if to be exported | |
35 | # 4 "no" if not to be added to the hint table else the appropriate enum cxx_dialect value | |
36 | # 5 optional, a string used after #if in a line inserted first to enable conditional definitions | |
37 | ||
38 | ||
39 | def print_condition(prev, e): | |
40 | if len(e) > 4 and e[4] != '': | |
41 | if not prev or prev != e[4]: | |
42 | if prev: | |
43 | print('#endif') | |
44 | print(f'#if {e[4]}') | |
45 | return e[4] | |
46 | if prev: | |
47 | print('#endif') | |
48 | return None | |
49 | ||
50 | ||
51 | def export(script, content): | |
52 | print("""// This file is auto-generated by {:s}. | |
53 | #if __cplusplus <= 202002L | |
54 | # if __cplusplus == 202002L | |
55 | # ifdef __STRICT_ANSI__ | |
56 | # error "module `std' is only available before C++23 if using -std=gnu++20" | |
57 | # endif | |
58 | # else | |
59 | # error "module `std' is not available before C++23" | |
60 | # endif | |
61 | #endif | |
62 | ||
63 | export module std; | |
64 | ||
65 | import <bits/stdc++.h>; | |
66 | ||
67 | // new/delete operators in global namespace from <new> | |
68 | export using ::operator new; | |
69 | export using ::operator delete; | |
70 | export using ::operator new[]; | |
71 | export using ::operator delete[];""".format(script)) | |
72 | header = '' | |
73 | printed_header = False | |
74 | cond = None | |
75 | for e in content: | |
76 | if e[0] != header: | |
77 | header = e[0] | |
78 | printed_header = False | |
79 | if e[2] != 0: | |
80 | if not printed_header: | |
81 | if cond: | |
82 | print('#endif') | |
83 | cond = None | |
84 | print(f'\n// {header}') | |
85 | printed_header = True | |
86 | cond = print_condition(cond, e) | |
87 | print(f'export using std::{e[1]};') | |
88 | if cond: | |
89 | print('#endif') | |
90 | ||
91 | ||
92 | def hints(script, content): | |
93 | print("""%language=C++ | |
94 | %define class-name std_name_hint_lookup | |
95 | %struct-type | |
96 | %{{ | |
97 | /* This file is auto-generated by {:s}. */ | |
98 | /* Copyright (C) {:s} Free Software Foundation, Inc. | |
99 | ||
100 | This file is part of GCC. | |
101 | ||
102 | GCC is free software; you can redistribute it and/or modify it under | |
103 | the terms of the GNU General Public License as published by the Free | |
104 | Software Foundation; either version 3, or (at your option) any later | |
105 | version. | |
106 | ||
107 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
108 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
109 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
110 | for more details. | |
111 | ||
112 | You should have received a copy of the GNU General Public License | |
113 | along with GCC; see the file COPYING3. If not see | |
114 | <http://www.gnu.org/licenses/>. */ | |
115 | %}} | |
116 | struct std_name_hint | |
117 | {{ | |
118 | /* A name within "std::". */ | |
119 | const char *name; | |
120 | ||
121 | /* The header name defining it within the C++ Standard Library | |
122 | (with '<' and '>'). */ | |
123 | const char* header; | |
124 | ||
125 | /* The dialect of C++ in which this was added. */ | |
126 | enum cxx_dialect min_dialect; | |
127 | }}; | |
128 | %% | |
129 | # The standard-defined types, functions, and options in the std:: namespace | |
130 | # as defined in the C++ language specification. The result is used in the | |
131 | # get_std_name_hint functions. | |
132 | # throws an exception. | |
133 | #""".format(script, time.strftime('%Y'))) | |
134 | header = '' | |
135 | printed_header = False | |
136 | for e in content: | |
137 | if e[0] != header: | |
138 | header = e[0] | |
139 | printed_header = False | |
140 | if e[3] != 'no': | |
141 | if not printed_header: | |
142 | print(f'# {header}') | |
143 | printed_header = True | |
144 | print(f'{e[1]}, "{e[0]}", {e[3]}') | |
145 | ||
146 | ||
147 | def remove_comment(f): | |
148 | for row in f: | |
149 | row = row.strip() | |
150 | if row[0] != '#': | |
151 | yield row | |
152 | ||
153 | ||
154 | modes = { | |
155 | 'export': export, | |
156 | 'hints': hints | |
157 | } | |
158 | ||
159 | ||
160 | def usage(script): | |
161 | print(f'Usage: {script} [{"|".join(modes.keys())}] CSVFILE') | |
162 | exit(1) | |
163 | ||
164 | ||
165 | def main(argv): | |
166 | if len(argv) < 3: | |
167 | usage(argv[0] if len(argv) > 0 else '???') | |
168 | ||
169 | script = argv[0] | |
170 | mode = argv[1] | |
171 | filename = argv[2] | |
172 | ||
173 | if mode not in modes: | |
174 | print(f"{script}: unrecognized mode '{mode}'") | |
175 | usage(script) | |
176 | ||
177 | try: | |
178 | with open(filename, 'r') as csvfile: | |
179 | modes[mode](os.path.basename(script), sorted(csv.reader(remove_comment(csvfile), delimiter=','))) | |
180 | except FileNotFoundError: | |
181 | print(f"{script}: cannot find CSV file '{filename}'") | |
182 | exit(1) | |
183 | except PermissionError: | |
184 | print(f"{script}: insufficient permission to read CSV file '{filename}'") | |
185 | exit(1) | |
186 | ||
187 | ||
188 | if __name__ == '__main__': | |
189 | import sys | |
190 | main(sys.argv) |