1+ # Copyright (c) 2025 Joe Downs. All rights reserved.
2+ #
3+ # $COPYRIGHT$
4+ #
5+ # Additional copyrights may follow
6+ #
7+ # $HEADER$
8+ #
9+
10+ import argparse
111import re
2- import textwrap
3- import consts
4- from consts import Lang
12+ import json
13+ from pathlib import Path
514
615import pympistandard as std
716
817# ============================= Constants / Globals ============================
18+ DIR = Path ("." )
19+ OUTPUT = DIR / "mpi.h"
20+ JSON_PATH = DIR / "abi.json"
921
1022ABI_INTERNAL = "_ABI_INTERNAL"
1123
12- categories = {}
13- mangle_names = True
24+ categories_dict = {}
25+ MANGLE_NAMES = False
1426
15- internal_datatypes = [
27+ INTERNAL_DATATYPES = [
1628 "MPI_Comm" ,
1729 "MPI_Datatype" ,
1830 "MPI_Errhandler" ,
2638 "MPI_Win" ,
2739]
2840
41+ ENUM_CATEGORIES = [
42+ "ERROR_CLASSES" ,
43+ "MODE_CONSTANTS" ,
44+ "ASSORTED_CONSTANTS" ,
45+ "THREADS_CONSTANTS" ,
46+ "FILE_OPERATIONS_CONSTANTS" ,
47+ "DATATYPE_DECODING_CONSTANTS" ,
48+ "F90_DATATYPE_MATCHING_CONSTANTS" ,
49+ "COMMUNICATOR_GROUP_COMP_RESULTS" ,
50+ "TOPOLOGIES" ,
51+ "COMMUNICATOR_SPLIT_TYPE" ,
52+ "WINDOW_LOCK_TYPE_CONSTANTS" ,
53+ "WINDOW_CREATE_FLAVORS" ,
54+ "WINDOW_MODELS" ,
55+ "FILE_POS_CONSTANTS" ,
56+ "FILE_OP_CONSTANTS" ,
57+ "ENV_INQ_AND_ATTR_KEYS" ,
58+ "FORTRAN_STATUS_ARRAY_SIZE_AND_INDEX_C" ,
59+ "C_PREPROCESSOR_CONSTANTS_FORTRAN_PARAMETERS" ,
60+ "TOOL_INFO_IFACE_VERBOSITY_LEVELS" ,
61+ "TOOL_INFO_IFACE_VAR_ASSOCIATIONS" ,
62+ "TOOL_INFO_IFACE_VAR_SCOPES" ,
63+ "TOOL_INFO_IFACE_PVAR_CLASSES" ,
64+ "TOOL_INFO_IFACE_SOURCE_ORDERINGS" ,
65+ "TOOL_INFO_IFACE_CB_SAFETY_REQ_LEVELS" ,
66+ ]
67+
68+
69+ # ============================== Argument Parsing ==============================
70+ parser = argparse .ArgumentParser ()
71+ parser .add_argument ("--abi-json" , type = str , help = f"path to ABI JSON file [{ DIR } /]" )
72+ parser .add_argument ("-o" , "--output" , type = str , help = "output directory for the header file" )
73+ parser .add_argument ("--mangle-names" , help = "enable name mangling for constants and datatypes" , action = "store_true" )
74+ parser .add_argument ("--no-mangle" , help = "disable name mangling (default)" , action = "store_true" )
75+
76+ args = parser .parse_args ()
77+
78+ if args .abi_json :
79+ JSON_PATH = Path (args .abi_json )
80+ if args .mangle_names :
81+ MANGLE_NAMES = True
82+ if args .no_mangle :
83+ MANGLE_NAMES = False
84+ if args .output :
85+ OUTPUT = Path (args .output )
86+
87+ # ================================== Load JSON =================================
88+ with open (JSON_PATH ) as f :
89+ abi = json .load (f )
90+
91+ CONSTS = abi ["constants" ]
92+ CATEGORIES = abi ["categories" ]
93+
94+ # ==============================================================================
95+
2996# Populating the `categories` dictionary
30- for category in consts . categories .values ():
97+ for category in CATEGORIES .values ():
3198 name = category ["name" ]
32- categories [name ] = []
33- for value in consts . consts .values ():
99+ categories_dict [name ] = []
100+ for value in CONSTS .values ():
34101 if value ["category" ] == name :
35- categories [name ].append (value )
102+ categories_dict [name ].append (value )
36103
37104# ================================== Functions =================================
105+ # TODO: we need to add/fix/figure out the pympistandard's way for properly
106+ # defining callback functions
107+ def cb_declaration (proc_expression ):
108+ func_str = str (proc_expression ).replace (r"\ldots" , "..." )
109+ func_str_list = func_str .split ()
110+ func_name , arg_1 = func_str_list [2 ].split ("(" )
111+ decl_string = f"{ ' ' .join (func_str_list [:2 ])} ({ func_name } )({ arg_1 } { ' ' .join (func_str_list [3 :])} ;\n "
112+ return decl_string
38113
39114def output_constant (const , use_enum : bool , mangle_name : bool ):
40115 name = const ["name" ]
@@ -57,7 +132,7 @@ def output_constant(const, use_enum: bool, mangle_name: bool):
57132
58133# ========================= Manipulate Template Header =========================
59134lines = []
60- with open (consts . DIR / "abi.h.in" , 'r' ) as header_in :
135+ with open (DIR / "abi.h.in" , 'r' ) as header_in :
61136 lines = header_in .readlines ()
62137
63138# Match lines that start with `$CATEGORY:`. Any amount of whitespace is allowed
@@ -74,13 +149,13 @@ def output_constant(const, use_enum: bool, mangle_name: bool):
74149 category = category .group (1 )
75150 use_enum = False
76151 # Only some values should be in `enums`, otherwise just use `#define`s
77- if category in consts . ENUM_CATEGORIES :
152+ if category in ENUM_CATEGORIES :
78153 use_enum = True
79154 if use_enum :
80155 output .append ("enum {\n " )
81156 # Print out each `#define` / assignment for the constants
82- for constant in categories [category ]:
83- line = output_constant (constant , use_enum , mangle_names )
157+ for constant in categories_dict [category ]:
158+ line = output_constant (constant , use_enum , MANGLE_NAMES )
84159 if line is not None :
85160 output .append (line )
86161 if use_enum :
@@ -89,15 +164,6 @@ def output_constant(const, use_enum: bool, mangle_name: bool):
89164 output .append (line )
90165
91166# ============================= Function Prototypes ============================
92- # TODO: we need to add/fix/figure out the pympistandard's way for properly
93- # defining callback functions
94- def cb_declaration (proc_expression ):
95- func_str = str (proc_expression ).replace (r"\ldots" , "..." )
96- func_str_list = func_str .split ()
97- func_name , arg_1 = func_str_list [2 ].split ("(" )
98- decl_string = f"{ ' ' .join (func_str_list [:2 ])} ({ func_name } )({ arg_1 } { ' ' .join (func_str_list [3 :])} ;\n "
99- return decl_string
100-
101167std .use_api_version ()
102168
103169output .append ("\n " )
@@ -134,12 +200,15 @@ def cb_declaration(proc_expression):
134200
135201# Iterate through all lines and replace datatypes with their internal ABI
136202# counterparts
137- if mangle_names :
203+ if MANGLE_NAMES :
138204 for i , line in enumerate (output ):
139205 mangled_line = line
140- for datatype in internal_datatypes :
141- mangled_line = mangled_line .replace (datatype , f"{ datatype } { ABI_INTERNAL } " )
206+ for datatype in INTERNAL_DATATYPES :
207+ # Need to include the extra space here or else we'll edit functions
208+ # like "MPI_Group_difference"
209+ datatype_pattern = r"([\( ]?)(" + datatype + r")([; \*]{1})"
210+ mangled_line = re .sub (datatype_pattern , f"\\ g<1>\\ g<2>{ ABI_INTERNAL } \\ g<3>" , mangled_line )
142211 output [i ] = mangled_line
143212
144- with open (consts . DIR / "abi.h" , 'tw' ) as header_out :
213+ with open (OUTPUT , 'tw' ) as header_out :
145214 header_out .writelines (output )
0 commit comments