| #!/usr/bin/env python3 |
| |
| # Copyright (C) 2022 Free Software Foundation, Inc. |
| # This file is part of GCC. |
| |
| # GCC is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 3, or (at your option) |
| # any later version. |
| |
| # GCC is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| |
| # You should have received a copy of the GNU General Public License |
| # along with GCC; see the file COPYING3. If not see |
| # <http://www.gnu.org/licenses/>. |
| |
| |
| # Generate gcc source files: |
| # - the export description of the standard C++ library module |
| # - the gperf tables used to hint at actions to fix problems |
| # related to missing symbols in the std:: namespace |
| |
| import csv |
| import os |
| import time |
| |
| # The CSV file contains the following columns: |
| # column value |
| # 1 header file, including angle brackets |
| # 2 symbol name without std:: prefix |
| # 3 nonzero if to be exported |
| # 4 "no" if not to be added to the hint table else the appropriate enum cxx_dialect value |
| # 5 optional, a string used after #if in a line inserted first to enable conditional definitions |
| |
| |
| def print_condition(prev, e): |
| if len(e) > 4 and e[4] != '': |
| if not prev or prev != e[4]: |
| if prev: |
| print('#endif') |
| print(f'#if {e[4]}') |
| return e[4] |
| if prev: |
| print('#endif') |
| return None |
| |
| |
| def export(script, content): |
| print("""// This file is auto-generated by {:s}. |
| #if __cplusplus <= 202002L |
| # if __cplusplus == 202002L |
| # ifdef __STRICT_ANSI__ |
| # error "module `std' is only available before C++23 if using -std=gnu++20" |
| # endif |
| # else |
| # error "module `std' is not available before C++23" |
| # endif |
| #endif |
| |
| export module std; |
| |
| import <bits/stdc++.h>; |
| |
| // new/delete operators in global namespace from <new> |
| export using ::operator new; |
| export using ::operator delete; |
| export using ::operator new[]; |
| export using ::operator delete[];""".format(script)) |
| header = '' |
| printed_header = False |
| cond = None |
| for e in content: |
| if e[0] != header: |
| header = e[0] |
| printed_header = False |
| if e[2] != 0: |
| if not printed_header: |
| if cond: |
| print('#endif') |
| cond = None |
| print(f'\n// {header}') |
| printed_header = True |
| cond = print_condition(cond, e) |
| print(f'export using std::{e[1]};') |
| if cond: |
| print('#endif') |
| |
| |
| def hints(script, content): |
| print("""%language=C++ |
| %define class-name std_name_hint_lookup |
| %struct-type |
| %{{ |
| /* This file is auto-generated by {:s}. */ |
| /* Copyright (C) {:s} Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| %}} |
| struct std_name_hint |
| {{ |
| /* A name within "std::". */ |
| const char *name; |
| |
| /* The header name defining it within the C++ Standard Library |
| (with '<' and '>'). */ |
| const char* header; |
| |
| /* The dialect of C++ in which this was added. */ |
| enum cxx_dialect min_dialect; |
| }}; |
| %% |
| # The standard-defined types, functions, and options in the std:: namespace |
| # as defined in the C++ language specification. The result is used in the |
| # get_std_name_hint functions. |
| # throws an exception. |
| #""".format(script, time.strftime('%Y'))) |
| header = '' |
| printed_header = False |
| for e in content: |
| if e[0] != header: |
| header = e[0] |
| printed_header = False |
| if e[3] != 'no': |
| if not printed_header: |
| print(f'# {header}') |
| printed_header = True |
| print(f'{e[1]}, "{e[0]}", {e[3]}') |
| |
| |
| def remove_comment(f): |
| for row in f: |
| row = row.strip() |
| if row[0] != '#': |
| yield row |
| |
| |
| modes = { |
| 'export': export, |
| 'hints': hints |
| } |
| |
| |
| def usage(script): |
| print(f'Usage: {script} [{"|".join(modes.keys())}] CSVFILE') |
| exit(1) |
| |
| |
| def main(argv): |
| if len(argv) < 3: |
| usage(argv[0] if len(argv) > 0 else '???') |
| |
| script = argv[0] |
| mode = argv[1] |
| filename = argv[2] |
| |
| if mode not in modes: |
| print(f"{script}: unrecognized mode '{mode}'") |
| usage(script) |
| |
| try: |
| with open(filename, 'r') as csvfile: |
| modes[mode](os.path.basename(script), sorted(csv.reader(remove_comment(csvfile), delimiter=','))) |
| except FileNotFoundError: |
| print(f"{script}: cannot find CSV file '{filename}'") |
| exit(1) |
| except PermissionError: |
| print(f"{script}: insufficient permission to read CSV file '{filename}'") |
| exit(1) |
| |
| |
| if __name__ == '__main__': |
| import sys |
| main(sys.argv) |