From ca0405752b09a0fb820d4be6f1e14a346614f21d Mon Sep 17 00:00:00 2001 From: Arik Sosman Date: Tue, 12 Jan 2021 11:40:47 -0500 Subject: [PATCH] Somewhat redundant changes (new file_ext, arg parse, etc) --- config.py | 65 +++++++++++++++++++++++++++++++++++++++++ genbindings.py | 68 ++++++++++++++++++++++++++----------------- java_strings.py | 8 ++++- language_constants.py | 2 ++ typescript_strings.py | 8 ++++- 5 files changed, 123 insertions(+), 28 deletions(-) create mode 100644 config.py create mode 100644 language_constants.py diff --git a/config.py b/config.py new file mode 100644 index 00000000..c16048e2 --- /dev/null +++ b/config.py @@ -0,0 +1,65 @@ +from enum import Enum +import argparse +import os +import sys + + +class Language(Enum): + Java = 1 + TypeScript = 2 + + +class Configurator: + language: Language + debug: bool + lightning_h_path: str + bindings_output_directory_path: str + output_c_path: str + output_blob_path: str + + def __init__(self, + lightning_h_path: str, + output_blob_path: str, + bindings_output_directory_path: str, + output_c_path: str, + language: Language = Language.TypeScript, + debug: bool = False): + self.language = language + self.debug = debug + + self.lightning_h_path = lightning_h_path + self.output_blob_path = output_blob_path + self.bindings_output_directory_path = bindings_output_directory_path + self.output_c_path = output_c_path + + +def setup(): + parser = argparse.ArgumentParser(description='Generate Java or Typescript bindings.') + parser.add_argument('lightning', type=str, help='Path to lightning.h input') + parser.add_argument('output-blob', type=str, help='Path to output blob file') + parser.add_argument('bindings-dir', type=str, help='Path to bindings output directory') + parser.add_argument('output-c', type=str, help='Path to output.c') + parser.add_argument('-l', '--language', type=str, choices=['java', 'typescript'], help='Language', + default='java') + parser.add_argument('-d', '--debug', help='Debug', action='store_true', default=False) + args = parser.parse_args() + + language = Language.Java + if args.language == 'typescript': + language = Language.TypeScript + + bindings_directory_input = getattr(args, 'bindings-dir') + bindings_directory = os.path.abspath(bindings_directory_input) + if not os.path.isdir(bindings_directory): + print('Bindings output directory must, in fact, be a directory!', bindings_directory, file=sys.stderr) + sys.exit(1) + + configuration = Configurator( + lightning_h_path=args.lightning, + output_blob_path=getattr(args, 'output-blob'), + bindings_output_directory_path=bindings_directory, + output_c_path=getattr(args, 'output-c'), + debug=args.debug, + language=language + ) + return configuration diff --git a/genbindings.py b/genbindings.py index e684a420..b744da93 100755 --- a/genbindings.py +++ b/genbindings.py @@ -1,26 +1,31 @@ #!/usr/bin/env python3 import sys, re -if len(sys.argv) != 7: - print("USAGE: /path/to/lightning.h /path/to/bindings/output /path/to/bindings/ /path/to/bindings/output.c debug lang") - sys.exit(1) +import config +from config import Language +import os -if sys.argv[5] == "false": - DEBUG = False -elif sys.argv[5] == "true": - DEBUG = True -else: - print("debug should be true or false and indicates whether to track allocations and ensure we don't leak") - sys.exit(1) +configuration = config.setup() -if sys.argv[6] == "java": +output_language = configuration.language +if output_language == Language.Java: from java_strings import Consts -elif sys.argv[6] == "typescript": +elif output_language == Language.TypeScript: from typescript_strings import Consts else: print("Only java or typescript can be set for lang") sys.exit(1) -consts = Consts(DEBUG) + +consts = Consts(configuration.debug) + +path_to_lightning_header = configuration.lightning_h_path +path_to_output_blob = configuration.output_blob_path +path_to_bindings_directory = configuration.bindings_output_directory_path +path_to_c_file = configuration.output_c_path + + + + from bindingstypes import * @@ -55,6 +60,14 @@ def camel_to_snake(s): lastund = True return (ret + lastchar.lower()).strip("_") + +def recursiveOpenFile(path, *args): + output_directory_path = os.path.dirname(path) + if not os.path.isdir(output_directory_path): + os.makedirs(output_directory_path) + return open(path, *args) + + unitary_enums = set() complex_enums = set() opaque_structs = set() @@ -315,7 +328,7 @@ reg_fn_regex = re.compile("([A-Za-z_0-9\* ]* \*?)([a-zA-Z_0-9]*)\((.*)\);$") clone_fns = set() constructor_fns = {} c_array_class_caches = set() -with open(sys.argv[1]) as in_h: +with open(path_to_lightning_header) as in_h: for line in in_h: reg_fn = reg_fn_regex.match(line) if reg_fn is not None: @@ -339,7 +352,7 @@ write_c("static inline struct LDKThirtyTwoBytes ThirtyTwoBytes_clone(const struc java_c_types_none_allowed = False # C structs created by cbindgen are declared in dependency order -with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: +with open(path_to_lightning_header) as in_h, open(path_to_output_blob, "w") as out_java: def map_type(fn_arg, print_void, ret_arr_len, is_free, holds_ref): ty_info = java_c_types(fn_arg, ret_arr_len) return map_type_with_info(ty_info, print_void, ret_arr_len, is_free, holds_ref) @@ -738,6 +751,8 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: to_hu_conv = "TODO 3", to_hu_conv_name = None, from_hu_conv = None) # its a pointer, no conv needed assert False # We should have handled every case by now. + + def map_fn(line, re_match, ret_arr_len, c_call_string): out_java.write("\t// " + line) out_java.write("\tpublic static native ") @@ -788,7 +803,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java_struct = None if ("LDK" + struct_meth in opaque_structs or "LDK" + struct_meth in trait_structs) and not is_free: - out_java_struct = open(f"{sys.argv[3]}/structs/{struct_meth}{consts.file_ext}", "a") + out_java_struct = open(f"{path_to_bindings_directory}/structs/{struct_meth}.{consts.file_extension}", "a") if not args_known: out_java_struct.write("\t// Skipped " + re_match.group(2) + "\n") out_java_struct.close() @@ -909,7 +924,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java_struct.close() def map_unitary_enum(struct_name, field_lines): - with open(f"{sys.argv[3]}/enums/{struct_name}{consts.file_ext}", "w") as out_java_enum: + with recursiveOpenFile(f"{path_to_bindings_directory}/enums/{struct_name}.{consts.file_extension}", "w") as out_java_enum: unitary_enums.add(struct_name) for idx, struct_line in enumerate(field_lines): if idx == 0: @@ -924,7 +939,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: write_c(c_out) out_java_enum.write(native_file_out) out_java.write(native_out) - + def map_complex_enum(struct_name, union_enum_items): java_hu_type = struct_name.replace("LDK", "") complex_enums.add(struct_name) @@ -1029,7 +1044,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: out_java_enum.write("}\n") def map_trait(struct_name, field_var_lines, trait_fn_lines): - with open(f"{sys.argv[3]}/structs/{struct_name.replace('LDK', '')}{consts.file_ext}", "w") as out_java_trait: + with open(f"{path_to_bindings_directory}/structs/{struct_name.replace('LDK', '')}.{consts.file_extension}", "w") as out_java_trait: field_var_convs = [] for var_line in field_var_lines: if var_line.group(1) in trait_structs: @@ -1272,7 +1287,7 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: def map_result(struct_name, res_ty, err_ty): result_types.add(struct_name) human_ty = struct_name.replace("LDKCResult", "Result") - with open(f"{sys.argv[3]}/structs/{human_ty}{consts.file_ext}", "w") as out_java_struct: + with open(f"{path_to_bindings_directory}/structs/{human_ty}.{consts.file_extension}", "w") as out_java_struct: out_java_struct.write(consts.hu_struct_file_prefix) out_java_struct.write("public class " + human_ty + " extends CommonBase {\n") out_java_struct.write("\tprivate " + human_ty + "(Object _dummy, long ptr) { super(ptr); }\n") @@ -1495,7 +1510,7 @@ public class bindings { """) - with open(f"{sys.argv[3]}/structs/CommonBase{consts.file_ext}", "a") as out_java_struct: + with recursiveOpenFile(f"{path_to_bindings_directory}/structs/CommonBase.{consts.file_extension}", "w") as out_java_struct: out_java_struct.write(consts.common_base) in_block_comment = False @@ -1586,7 +1601,7 @@ public class bindings { if is_opaque: opaque_structs.add(struct_name) - with open(f"{sys.argv[3]}/structs/{struct_name.replace('LDK', '')}{consts.file_ext}", "w") as out_java_struct: + with open(f"{path_to_bindings_directory}/structs/{struct_name.replace('LDK', '')}.{consts.file_extension}", "w") as out_java_struct: out_java_struct.write(consts.hu_struct_file_prefix) out_java_struct.write("public class " + struct_name.replace("LDK","") + " extends CommonBase") if struct_name.startswith("LDKLocked"): @@ -1672,7 +1687,7 @@ public class bindings { trait_structs.add(struct_name) map_trait(struct_name, field_var_lines, trait_fn_lines) elif struct_name == "LDKTxOut": - with open(f"{sys.argv[3]}/structs/TxOut{consts.file_ext}", "w") as out_java_struct: + with open(f"{path_to_bindings_directory}/structs/TxOut.{consts.file_extension}", "w") as out_java_struct: out_java_struct.write(consts.hu_struct_file_prefix) out_java_struct.write("public class TxOut extends CommonBase{\n") out_java_struct.write("\tTxOut(java.lang.Object _dummy, long ptr) { super(ptr); }\n") @@ -1719,12 +1734,13 @@ public class bindings { out_java.write("}\n") for struct_name in opaque_structs: - with open(f"{sys.argv[3]}/structs/{struct_name.replace('LDK', '')}{consts.file_ext}", "a") as out_java_struct: + with open(f"{path_to_bindings_directory}/structs/{struct_name.replace('LDK', '')}.{consts.file_extension}", "a") as out_java_struct: out_java_struct.write("}\n") for struct_name in trait_structs: - with open(f"{sys.argv[3]}/structs/{struct_name.replace('LDK', '')}{consts.file_ext}", "a") as out_java_struct: + with open(f"{path_to_bindings_directory}/structs/{struct_name.replace('LDK', '')}.{consts.file_extension}", "a") as out_java_struct: out_java_struct.write("}\n") -with open(sys.argv[4], "w") as out_c: +with open(path_to_c_file, "w") as out_c: out_c.write(consts.c_file_pfx) out_c.write(consts.init_str(c_array_class_caches)) out_c.write(c_file) + diff --git a/java_strings.py b/java_strings.py index 5aefd223..080f3b17 100644 --- a/java_strings.py +++ b/java_strings.py @@ -1,7 +1,13 @@ from bindingstypes import * -class Consts: +from language_constants import LanguageConstants + +class Consts(LanguageConstants): def __init__(self, DEBUG): + super().__init__() + + self.file_extension = 'java' + self.common_base = """package org.ldk.structs; import java.util.LinkedList; class CommonBase { diff --git a/language_constants.py b/language_constants.py new file mode 100644 index 00000000..d7db4f2c --- /dev/null +++ b/language_constants.py @@ -0,0 +1,2 @@ +class LanguageConstants: + file_extension: str diff --git a/typescript_strings.py b/typescript_strings.py index dccd8cf3..b4390b71 100644 --- a/typescript_strings.py +++ b/typescript_strings.py @@ -1,5 +1,11 @@ -class Consts: +from language_constants import LanguageConstants + +class Consts(LanguageConstants): + def __init__(self, DEBUG): + super().__init__() + self.file_extension = 'ts' + self.common_base = """ export default class CommonBase { ptr: number; -- 2.39.5