aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2022-11-03 18:41:41 +0100
committerAndre Weissflog <floooh@gmail.com>2022-11-03 18:41:41 +0100
commit471f125e0aaa0b5c1201c754812c14cbb8b98ff1 (patch)
treee80e328852e9a34c158c72e9e96263c75c82e6b5
parent818d12e9970fd47e4ded16666bb5585717d22842 (diff)
Fix language bindings:
- clang-14 ast-dump has changed for array types, fix works both for new and old format - start moving common helper functions into gen_util.py
-rw-r--r--bindgen/gen_nim.py72
-rw-r--r--bindgen/gen_odin.py68
-rw-r--r--bindgen/gen_util.py57
-rw-r--r--bindgen/gen_zig.py113
4 files changed, 123 insertions, 187 deletions
diff --git a/bindgen/gen_nim.py b/bindgen/gen_nim.py
index e66b46f2..06e5b641 100644
--- a/bindgen/gen_nim.py
+++ b/bindgen/gen_nim.py
@@ -6,7 +6,8 @@
# - reference: https://nim-lang.org/docs/nep1.html
#-------------------------------------------------------------------------------
import gen_ir
-import re, os, shutil, sys
+import gen_util as util
+import os, shutil, sys
module_names = {
'sg_': 'gfx',
@@ -151,9 +152,6 @@ xor
yield
""".split() + common_prim_types
-re_1d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]$")
-re_2d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]\[\d*\]$")
-
struct_types = []
enum_types = []
out_lines = ''
@@ -243,15 +241,6 @@ def is_struct_type(s):
def is_enum_type(s):
return s in enum_types
-def is_string_ptr(s):
- return s == "const char *"
-
-def is_const_void_ptr(s):
- return s == "const void *"
-
-def is_void_ptr(s):
- return s == "void *"
-
def is_const_prim_ptr(s):
for prim_type in prim_types:
if s == f"const {prim_type} *":
@@ -270,34 +259,9 @@ def is_const_struct_ptr(s):
return True
return False
-def is_func_ptr(s):
- return '(*)' in s
-
-def is_1d_array_type(s):
- return re_1d_array.match(s) is not None
-
-def is_2d_array_type(s):
- return re_2d_array.match(s) is not None
-
-def is_array_type(s):
- return is_1d_array_type(s) or is_2d_array_type(s)
-
def type_default_value(s):
return prim_defaults[s]
-def extract_array_type(s):
- return s[:s.index('[')].strip()
-
-def extract_array_sizes(s):
- return s[s.index('['):].replace('[', ' ').replace(']', ' ').split()
-
-def extract_ptr_type(s):
- tokens = s.split()
- if tokens[0] == 'const':
- return tokens[1]
- else:
- return tokens[0]
-
def funcptr_args(field_type, prefix):
tokens = field_type[field_type.index('(*)')+4:-1].split(',')
s = ""
@@ -328,31 +292,31 @@ def as_nim_type(ctype, prefix, struct_ptr_as_value=False):
return as_nim_type_name(ctype, prefix)
elif is_enum_type(ctype):
return as_nim_type_name(ctype, prefix)
- elif is_string_ptr(ctype):
+ elif util.is_string_ptr(ctype):
return "cstring"
- elif is_void_ptr(ctype) or is_const_void_ptr(ctype):
+ elif util.is_void_ptr(ctype) or util.is_const_void_ptr(ctype):
return "pointer"
elif is_const_struct_ptr(ctype):
- nim_type = as_nim_type(extract_ptr_type(ctype), prefix)
+ nim_type = as_nim_type(util.extract_ptr_type(ctype), prefix)
if struct_ptr_as_value:
return f"{nim_type}"
else:
return f"ptr {nim_type}"
elif is_prim_ptr(ctype) or is_const_prim_ptr(ctype):
- return f"ptr {as_nim_type(extract_ptr_type(ctype), prefix)}"
- elif is_func_ptr(ctype):
+ return f"ptr {as_nim_type(util.extract_ptr_type(ctype), prefix)}"
+ elif util.is_func_ptr(ctype):
args = funcptr_args(ctype, prefix)
res = funcptr_result(ctype, prefix)
if res != "":
res = ":" + res
return f"proc({args}){res} {{.cdecl.}}"
- elif is_1d_array_type(ctype):
- array_ctype = extract_array_type(ctype)
- array_sizes = extract_array_sizes(ctype)
+ elif util.is_1d_array_type(ctype):
+ array_ctype = util.extract_array_type(ctype)
+ array_sizes = util.extract_array_sizes(ctype)
return f'array[{array_sizes[0]}, {as_nim_type(array_ctype, prefix)}]'
- elif is_2d_array_type(ctype):
- array_ctype = extract_array_type(ctype)
- array_sizes = extract_array_sizes(ctype)
+ elif util.is_2d_array_type(ctype):
+ array_ctype = util.extract_array_type(ctype)
+ array_sizes = util.extract_array_sizes(ctype)
return f'array[{array_sizes[0]}, array[{array_sizes[1]}, {as_nim_type(array_ctype, prefix)}]]'
else:
sys.exit(f"ERROR as_nim_type: {ctype}")
@@ -468,19 +432,19 @@ def gen_func_nim(decl, prefix):
def gen_array_converters(decl, prefix):
for field in decl['fields']:
- if is_array_type(field['type']):
- array_type = extract_array_type(field['type'])
- array_sizes = extract_array_sizes(field['type'])
+ if util.is_array_type(field['type']):
+ array_type = util.extract_array_type(field['type'])
+ array_sizes = util.extract_array_sizes(field['type'])
struct_name = as_nim_struct_name(decl, prefix)
field_name = as_nim_field_name(field, prefix, check_private=False)
array_base_type = as_nim_type(array_type, prefix)
- if is_1d_array_type(field['type']):
+ if util.is_1d_array_type(field['type']):
n = array_sizes[0]
l(f'converter to{struct_name}{field_name}*[N:static[int]](items: array[N, {array_base_type}]): array[{n}, {array_base_type}] =')
l(f' static: assert(N < {n})')
l(f' for index,item in items.pairs: result[index]=item')
l('')
- elif is_2d_array_type(field['type']):
+ elif util.is_2d_array_type(field['type']):
x = array_sizes[1]
y = array_sizes[0]
l(f'converter to{struct_name}{field_name}*[Y:static[int], X:static[int]](items: array[Y, array[X, {array_base_type}]]): array[{y}, array[{x}, {array_base_type}]] =')
diff --git a/bindgen/gen_odin.py b/bindgen/gen_odin.py
index 00f6f083..65703815 100644
--- a/bindgen/gen_odin.py
+++ b/bindgen/gen_odin.py
@@ -4,7 +4,8 @@
# Generate Odin bindings.
#-------------------------------------------------------------------------------
import gen_ir
-import re, os, shutil, sys
+import gen_util as util
+import os, shutil, sys
bindings_root = 'sokol-odin'
c_root = f'{bindings_root}/c'
@@ -128,9 +129,6 @@ prim_defaults = {
'size_t': '0'
}
-re_1d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]$")
-re_2d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]\[\d*\]$")
-
struct_types = []
enum_types = []
enum_items = {}
@@ -218,15 +216,6 @@ def is_struct_type(s):
def is_enum_type(s):
return s in enum_types
-def is_string_ptr(s):
- return s == "const char *"
-
-def is_const_void_ptr(s):
- return s == "const void *"
-
-def is_void_ptr(s):
- return s == "void *"
-
def is_const_prim_ptr(s):
for prim_type in prim_types:
if s == f"const {prim_type} *":
@@ -245,31 +234,9 @@ def is_const_struct_ptr(s):
return True
return False
-def is_func_ptr(s):
- return '(*)' in s
-
-def is_1d_array_type(s):
- return re_1d_array.match(s) is not None
-
-def is_2d_array_type(s):
- return re_2d_array.match(s) is not None
-
def type_default_value(s):
return prim_defaults[s]
-def extract_array_type(s):
- return s[:s.index('[')].strip()
-
-def extract_array_sizes(s):
- return s[s.index('['):].replace('[', ' ').replace(']', ' ').split()
-
-def extract_ptr_type(s):
- tokens = s.split()
- if tokens[0] == 'const':
- return tokens[1]
- else:
- return tokens[0]
-
def map_type(type, prefix, sub_type):
if sub_type not in ['c_arg', 'odin_arg', 'struct_field']:
sys.exit(f"Error: map_type(): unknown sub_type '{sub_type}")
@@ -288,31 +255,31 @@ def map_type(type, prefix, sub_type):
return as_struct_or_enum_type(type, prefix)
elif is_enum_type(type):
return as_struct_or_enum_type(type, prefix)
- elif is_void_ptr(type):
+ elif util.is_void_ptr(type):
return "rawptr"
- elif is_const_void_ptr(type):
+ elif util.is_const_void_ptr(type):
return "rawptr"
- elif is_string_ptr(type):
+ elif util.is_string_ptr(type):
return "cstring"
elif is_const_struct_ptr(type):
# pass Odin struct args by value, not by pointer
if sub_type == 'odin_arg':
- return f"{as_struct_or_enum_type(extract_ptr_type(type), prefix)}"
+ return f"{as_struct_or_enum_type(util.extract_ptr_type(type), prefix)}"
else:
- return f"^{as_struct_or_enum_type(extract_ptr_type(type), prefix)}"
+ return f"^{as_struct_or_enum_type(util.extract_ptr_type(type), prefix)}"
elif is_prim_ptr(type):
- return f"^{as_prim_type(extract_ptr_type(type))}"
+ return f"^{as_prim_type(util.extract_ptr_type(type))}"
elif is_const_prim_ptr(type):
- return f"^{as_prim_type(extract_ptr_type(type))}"
- elif is_1d_array_type(type):
- array_type = extract_array_type(type)
- array_sizes = extract_array_sizes(type)
+ return f"^{as_prim_type(util.extract_ptr_type(type))}"
+ elif util.is_1d_array_type(type):
+ array_type = util.extract_array_type(type)
+ array_sizes = util.extract_array_sizes(type)
return f"[{array_sizes[0]}]{map_type(array_type, prefix, sub_type)}"
- elif is_2d_array_type(type):
- array_type = extract_array_type(type)
- array_sizes = extract_array_sizes(type)
+ elif util.is_2d_array_type(type):
+ array_type = util.extract_array_type(type)
+ array_sizes = util.extract_array_sizes(type)
return f"[{array_sizes[0]}][{array_sizes[1]}]{map_type(array_type, prefix, sub_type)}"
- elif is_func_ptr(type):
+ elif util.is_func_ptr(type):
res_type = funcptr_result_c(type, prefix)
res_str = '' if res_type == '' else f' -> {res_type}'
return f'proc "c" ({funcptr_args_c(type, prefix)}){res_str}'
@@ -532,6 +499,3 @@ def gen(c_header_path, c_prefix, dep_c_prefixes):
gen_module(ir, c_prefix, dep_c_prefixes)
with open(f"{module_root}/{ir['module']}/{ir['module']}.odin", 'w', newline='\n') as f_outp:
f_outp.write(out_lines)
-
-
-
diff --git a/bindgen/gen_util.py b/bindgen/gen_util.py
new file mode 100644
index 00000000..a76f4b2b
--- /dev/null
+++ b/bindgen/gen_util.py
@@ -0,0 +1,57 @@
+# common utility functions for all bindings generators
+import re
+
+re_1d_array = re.compile("^(?:const )?\w*\s*\*?\[\d*\]$")
+re_2d_array = re.compile("^(?:const )?\w*\s*\*?\[\d*\]\[\d*\]$")
+
+def is_1d_array_type(s):
+ return re_1d_array.match(s) is not None
+
+def is_2d_array_type(s):
+ return re_2d_array.match(s) is not None
+
+def is_array_type(s):
+ return is_1d_array_type(s) or is_2d_array_type(s)
+
+def extract_array_type(s):
+ return s[:s.index('[')].strip()
+
+def extract_array_sizes(s):
+ return s[s.index('['):].replace('[', ' ').replace(']', ' ').split()
+
+def is_string_ptr(s):
+ return s == "const char *"
+
+def is_const_void_ptr(s):
+ return s == "const void *"
+
+def is_void_ptr(s):
+ return s == "void *"
+
+def is_func_ptr(s):
+ return '(*)' in s
+
+def extract_ptr_type(s):
+ tokens = s.split()
+ if tokens[0] == 'const':
+ return tokens[1]
+ else:
+ return tokens[0]
+
+# PREFIX_BLA_BLUB to bla_blub
+def as_lower_snake_case(s, prefix):
+ outp = s.lower()
+ if outp.startswith(prefix):
+ outp = outp[len(prefix):]
+ return outp
+
+# prefix_bla_blub => blaBlub, PREFIX_BLA_BLUB => blaBlub
+def as_lower_camel_case(s, prefix):
+ outp = s.lower()
+ if outp.startswith(prefix):
+ outp = outp[len(prefix):]
+ parts = outp.split('_')
+ outp = parts[0]
+ for part in parts[1:]:
+ outp += part.capitalize()
+ return outp
diff --git a/bindgen/gen_zig.py b/bindgen/gen_zig.py
index 84a95147..aff1a65a 100644
--- a/bindgen/gen_zig.py
+++ b/bindgen/gen_zig.py
@@ -7,7 +7,9 @@
# - otherwise snake_case
#-------------------------------------------------------------------------------
import gen_ir
-import re, os, shutil, sys
+import os, shutil, sys
+
+import gen_util as util
module_names = {
'sg_': 'gfx',
@@ -90,8 +92,6 @@ prim_defaults = {
'size_t': '0'
}
-re_1d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]$")
-re_2d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]\[\d*\]$")
struct_types = []
enum_types = []
@@ -145,24 +145,6 @@ def check_override(name, default=None):
def check_ignore(name):
return name in ignores
-# PREFIX_BLA_BLUB to bla_blub
-def as_snake_case(s, prefix):
- outp = s.lower()
- if outp.startswith(prefix):
- outp = outp[len(prefix):]
- return outp
-
-# prefix_bla_blub => blaBlub
-def as_camel_case(s, prefix):
- outp = s.lower()
- if outp.startswith(prefix):
- outp = outp[len(prefix):]
- parts = outp.split('_')
- outp = parts[0]
- for part in parts[1:]:
- outp += part.capitalize()
- return outp
-
# PREFIX_ENUM_BLA => Bla, _PREFIX_ENUM_BLA => Bla
def as_enum_item_name(s):
outp = s.lstrip('_')
@@ -184,15 +166,6 @@ def is_struct_type(s):
def is_enum_type(s):
return s in enum_types
-def is_string_ptr(s):
- return s == "const char *"
-
-def is_const_void_ptr(s):
- return s == "const void *"
-
-def is_void_ptr(s):
- return s == "void *"
-
def is_const_prim_ptr(s):
for prim_type in prim_types:
if s == f"const {prim_type} *":
@@ -211,31 +184,9 @@ def is_const_struct_ptr(s):
return True
return False
-def is_func_ptr(s):
- return '(*)' in s
-
-def is_1d_array_type(s):
- return re_1d_array.match(s) is not None
-
-def is_2d_array_type(s):
- return re_2d_array.match(s) is not None
-
def type_default_value(s):
return prim_defaults[s]
-def extract_array_type(s):
- return s[:s.index('[')].strip()
-
-def extract_array_sizes(s):
- return s[s.index('['):].replace('[', ' ').replace(']', ' ').split()
-
-def extract_ptr_type(s):
- tokens = s.split()
- if tokens[0] == 'const':
- return tokens[1]
- else:
- return tokens[0]
-
def as_c_arg_type(arg_type, prefix):
if arg_type == "void":
return "void"
@@ -245,18 +196,18 @@ def as_c_arg_type(arg_type, prefix):
return as_zig_struct_type(arg_type, prefix)
elif is_enum_type(arg_type):
return as_zig_enum_type(arg_type, prefix)
- elif is_void_ptr(arg_type):
+ elif util.is_void_ptr(arg_type):
return "?*anyopaque"
- elif is_const_void_ptr(arg_type):
+ elif util.is_const_void_ptr(arg_type):
return "?*const anyopaque"
- elif is_string_ptr(arg_type):
+ elif util.is_string_ptr(arg_type):
return "[*c]const u8"
elif is_const_struct_ptr(arg_type):
- return f"[*c]const {as_zig_struct_type(extract_ptr_type(arg_type), prefix)}"
+ return f"[*c]const {as_zig_struct_type(util.extract_ptr_type(arg_type), prefix)}"
elif is_prim_ptr(arg_type):
- return f"[*c] {as_zig_prim_type(extract_ptr_type(arg_type))}"
+ return f"[*c] {as_zig_prim_type(util.extract_ptr_type(arg_type))}"
elif is_const_prim_ptr(arg_type):
- return f"[*c]const {as_zig_prim_type(extract_ptr_type(arg_type))}"
+ return f"[*c]const {as_zig_prim_type(util.extract_ptr_type(arg_type))}"
else:
sys.exit(f"Error as_c_arg_type(): {arg_type}")
@@ -274,19 +225,19 @@ def as_zig_arg_type(arg_prefix, arg_type, prefix):
return pre + as_zig_struct_type(arg_type, prefix)
elif is_enum_type(arg_type):
return pre + as_zig_enum_type(arg_type, prefix)
- elif is_void_ptr(arg_type):
+ elif util.is_void_ptr(arg_type):
return pre + "?*anyopaque"
- elif is_const_void_ptr(arg_type):
+ elif util.is_const_void_ptr(arg_type):
return pre + "?*const anyopaque"
- elif is_string_ptr(arg_type):
+ elif util.is_string_ptr(arg_type):
return pre + "[:0]const u8"
elif is_const_struct_ptr(arg_type):
# not a bug, pass const structs by value
- return pre + f"{as_zig_struct_type(extract_ptr_type(arg_type), prefix)}"
+ return pre + f"{as_zig_struct_type(util.extract_ptr_type(arg_type), prefix)}"
elif is_prim_ptr(arg_type):
- return pre + f"* {as_zig_prim_type(extract_ptr_type(arg_type))}"
+ return pre + f"* {as_zig_prim_type(util.extract_ptr_type(arg_type))}"
elif is_const_prim_ptr(arg_type):
- return pre + f"*const {as_zig_prim_type(extract_ptr_type(arg_type))}"
+ return pre + f"*const {as_zig_prim_type(util.extract_ptr_type(arg_type))}"
else:
sys.exit(f"ERROR as_zig_arg_type(): {arg_type}")
@@ -313,9 +264,9 @@ def funcptr_result_c(field_type):
res_type = field_type[:field_type.index('(*)')].strip()
if res_type == 'void':
return 'void'
- elif is_const_void_ptr(res_type):
+ elif util.is_const_void_ptr(res_type):
return '?*const anyopaque'
- elif is_void_ptr(res_type):
+ elif util.is_void_ptr(res_type):
return '?*anyopaque'
else:
sys.exit(f"ERROR funcptr_result_c(): {field_type}")
@@ -368,19 +319,19 @@ def gen_struct(decl, prefix):
l(f" {field_name}: {as_zig_struct_type(field_type, prefix)} = .{{ }},")
elif is_enum_type(field_type):
l(f" {field_name}: {as_zig_enum_type(field_type, prefix)} = .{enum_default_item(field_type)},")
- elif is_string_ptr(field_type):
+ elif util.is_string_ptr(field_type):
l(f" {field_name}: [*c]const u8 = null,")
- elif is_const_void_ptr(field_type):
+ elif util.is_const_void_ptr(field_type):
l(f" {field_name}: ?*const anyopaque = null,")
- elif is_void_ptr(field_type):
+ elif util.is_void_ptr(field_type):
l(f" {field_name}: ?*anyopaque = null,")
elif is_const_prim_ptr(field_type):
- l(f" {field_name}: ?[*]const {as_zig_prim_type(extract_ptr_type(field_type))} = null,")
- elif is_func_ptr(field_type):
+ l(f" {field_name}: ?[*]const {as_zig_prim_type(util.extract_ptr_type(field_type))} = null,")
+ elif util.is_func_ptr(field_type):
l(f" {field_name}: ?fn({funcptr_args_c(field_type, prefix)}) callconv(.C) {funcptr_result_c(field_type)} = null,")
- elif is_1d_array_type(field_type):
- array_type = extract_array_type(field_type)
- array_sizes = extract_array_sizes(field_type)
+ elif util.is_1d_array_type(field_type):
+ array_type = util.extract_array_type(field_type)
+ array_sizes = util.extract_array_sizes(field_type)
if is_prim_type(array_type) or is_struct_type(array_type):
if is_prim_type(array_type):
zig_type = as_zig_prim_type(array_type)
@@ -396,13 +347,13 @@ def gen_struct(decl, prefix):
t0 = f"[{array_sizes[0]}]{zig_type}"
t1 = f"[_]{zig_type}"
l(f" {field_name}: {t0} = {t1}{{{def_val}}} ** {array_sizes[0]},")
- elif is_const_void_ptr(array_type):
+ elif util.is_const_void_ptr(array_type):
l(f" {field_name}: [{array_sizes[0]}]?*const anyopaque = [_]?*const anyopaque {{ null }} ** {array_sizes[0]},")
else:
sys.exit(f"ERROR gen_struct: array {field_name}: {field_type} => {array_type} [{array_sizes[0]}]")
- elif is_2d_array_type(field_type):
- array_type = extract_array_type(field_type)
- array_sizes = extract_array_sizes(field_type)
+ elif util.is_2d_array_type(field_type):
+ array_type = util.extract_array_type(field_type)
+ array_sizes = util.extract_array_sizes(field_type)
if is_prim_type(array_type):
zig_type = as_zig_prim_type(array_type)
def_val = type_default_value(array_type)
@@ -420,7 +371,7 @@ def gen_struct(decl, prefix):
def gen_consts(decl, prefix):
for item in decl['items']:
item_name = check_override(item['name'])
- l(f"pub const {as_snake_case(item_name, prefix)} = {item['value']};")
+ l(f"pub const {util.as_lower_snake_case(item_name, prefix)} = {item['value']};")
def gen_enum(decl, prefix):
enum_name = check_override(decl['name'])
@@ -439,7 +390,7 @@ def gen_func_c(decl, prefix):
def gen_func_zig(decl, prefix):
c_func_name = decl['name']
- zig_func_name = as_camel_case(check_override(decl['name']), prefix)
+ zig_func_name = util.as_lower_camel_case(check_override(decl['name']), prefix)
zig_res_type = funcdecl_result_zig(decl, prefix)
l(f"pub fn {zig_func_name}({funcdecl_args_zig(decl, prefix)}) {zig_res_type} {{")
if is_zig_string(zig_res_type):
@@ -456,7 +407,7 @@ def gen_func_zig(decl, prefix):
arg_type = param_decl['type']
if is_const_struct_ptr(arg_type):
s += f"&{arg_name}"
- elif is_string_ptr(arg_type):
+ elif util.is_string_ptr(arg_type):
s += f"@ptrCast([*c]const u8,{arg_name})"
else:
s += arg_name