Updated ozz-animation to version 0.14.1.
This commit is contained in:
@@ -4,3 +4,5 @@
|
||||
__pycache__/
|
||||
sokol-nim/
|
||||
sokol-zig/
|
||||
sokol-odin/
|
||||
sokol-rust/
|
||||
|
||||
Vendored
+17
-7
@@ -1,8 +1,10 @@
|
||||
import os, gen_nim, gen_zig
|
||||
import os, gen_nim, gen_zig, gen_odin, gen_rust
|
||||
|
||||
tasks = [
|
||||
[ '../sokol_log.h', 'slog_', [] ],
|
||||
[ '../sokol_gfx.h', 'sg_', [] ],
|
||||
[ '../sokol_app.h', 'sapp_', [] ],
|
||||
[ '../sokol_glue.h', 'sapp_sg', ['sg_'] ],
|
||||
[ '../sokol_time.h', 'stm_', [] ],
|
||||
[ '../sokol_audio.h', 'saudio_', [] ],
|
||||
[ '../util/sokol_gl.h', 'sgl_', ['sg_'] ],
|
||||
@@ -10,18 +12,26 @@ tasks = [
|
||||
[ '../util/sokol_shape.h', 'sshape_', ['sg_'] ],
|
||||
]
|
||||
|
||||
# Odin
|
||||
gen_odin.prepare()
|
||||
for task in tasks:
|
||||
[c_header_path, main_prefix, dep_prefixes] = task
|
||||
gen_odin.gen(c_header_path, main_prefix, dep_prefixes)
|
||||
|
||||
# Nim
|
||||
gen_nim.prepare()
|
||||
for task in tasks:
|
||||
c_header_path = task[0]
|
||||
main_prefix = task[1]
|
||||
dep_prefixes = task[2]
|
||||
[c_header_path, main_prefix, dep_prefixes] = task
|
||||
gen_nim.gen(c_header_path, main_prefix, dep_prefixes)
|
||||
|
||||
# Zig
|
||||
gen_zig.prepare()
|
||||
for task in tasks:
|
||||
c_header_path = task[0]
|
||||
main_prefix = task[1]
|
||||
dep_prefixes = task[2]
|
||||
[c_header_path, main_prefix, dep_prefixes] = task
|
||||
gen_zig.gen(c_header_path, main_prefix, dep_prefixes)
|
||||
|
||||
# Rust
|
||||
gen_rust.prepare()
|
||||
for task in tasks:
|
||||
[c_header_path, main_prefix, dep_prefixes] = task
|
||||
gen_rust.gen(c_header_path, main_prefix, dep_prefixes)
|
||||
|
||||
Vendored
+7
-5
@@ -59,11 +59,11 @@ def parse_enum(decl):
|
||||
if 'inner' in item_decl:
|
||||
const_expr = item_decl['inner'][0]
|
||||
if const_expr['kind'] != 'ConstantExpr':
|
||||
sys.exit(f"ERROR: Enum values must be a ConstantExpr ({decl['name']})")
|
||||
if const_expr['valueCategory'] != 'rvalue':
|
||||
sys.exit(f"ERROR: Enum value ConstantExpr must be 'rvalue' ({decl['name']})")
|
||||
sys.exit(f"ERROR: Enum values must be a ConstantExpr ({item_decl['name']}), is '{const_expr['kind']}'")
|
||||
if const_expr['valueCategory'] != 'rvalue' and const_expr['valueCategory'] != 'prvalue':
|
||||
sys.exit(f"ERROR: Enum value ConstantExpr must be 'rvalue' or 'prvalue' ({item_decl['name']}), is '{const_expr['valueCategory']}'")
|
||||
if not ((len(const_expr['inner']) == 1) and (const_expr['inner'][0]['kind'] == 'IntegerLiteral')):
|
||||
sys.exit(f"ERROR: Enum value ConstantExpr must have exactly one IntegerLiteral ({decl['name']})")
|
||||
sys.exit(f"ERROR: Enum value ConstantExpr must have exactly one IntegerLiteral ({item_decl['name']})")
|
||||
item['value'] = const_expr['inner'][0]['value']
|
||||
if needs_value and 'value' not in item:
|
||||
sys.exit(f"ERROR: anonymous enum items require an explicit value")
|
||||
@@ -79,7 +79,7 @@ def parse_func(decl):
|
||||
if 'inner' in decl:
|
||||
for param in decl['inner']:
|
||||
if param['kind'] != 'ParmVarDecl':
|
||||
print(f"warning: ignoring func {decl['name']} (unsupported parameter type)")
|
||||
print(f" >> warning: ignoring func {decl['name']} (unsupported parameter type)")
|
||||
return None
|
||||
outp_param = {}
|
||||
outp_param['name'] = param['name']
|
||||
@@ -119,4 +119,6 @@ def gen(header_path, source_path, module, main_prefix, dep_prefixes):
|
||||
outp_decl['is_dep'] = is_dep
|
||||
outp_decl['dep_prefix'] = dep_prefix(decl, dep_prefixes)
|
||||
outp['decls'].append(outp_decl)
|
||||
with open(f'{module}.json', 'w') as f:
|
||||
f.write(json.dumps(outp, indent=2));
|
||||
return outp
|
||||
|
||||
Vendored
+383
-334
@@ -1,16 +1,19 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# Read output of gen_json.py and generate Zig language bindings.
|
||||
# Generate Nim bindings
|
||||
#
|
||||
# Nim coding style:
|
||||
# - types and constants are PascalCase
|
||||
# - functions, parameters, and fields are camelCase
|
||||
# - type identifiers are PascalCase, everything else is camelCase
|
||||
# - reference: https://nim-lang.org/docs/nep1.html
|
||||
#-------------------------------------------------------------------------------
|
||||
import gen_ir
|
||||
import json, re, os, shutil
|
||||
import gen_util as util
|
||||
import os, shutil, sys
|
||||
|
||||
module_names = {
|
||||
'slog_': 'log',
|
||||
'sg_': 'gfx',
|
||||
'sapp_': 'app',
|
||||
'sapp_sg': 'glue',
|
||||
'stm_': 'time',
|
||||
'saudio_': 'audio',
|
||||
'sgl_': 'gl',
|
||||
@@ -19,8 +22,10 @@ module_names = {
|
||||
}
|
||||
|
||||
c_source_paths = {
|
||||
'slog_': 'sokol-nim/src/sokol/c/sokol_log.c',
|
||||
'sg_': 'sokol-nim/src/sokol/c/sokol_gfx.c',
|
||||
'sapp_': 'sokol-nim/src/sokol/c/sokol_app.c',
|
||||
'sapp_sg': 'sokol-nim/src/sokol/c/sokol_glue.c',
|
||||
'stm_': 'sokol-nim/src/sokol/c/sokol_time.c',
|
||||
'saudio_': 'sokol-nim/src/sokol/c/sokol_audio.c',
|
||||
'sgl_': 'sokol-nim/src/sokol/c/sokol_gl.c',
|
||||
@@ -28,20 +33,57 @@ c_source_paths = {
|
||||
'sshape_': 'sokol-nim/src/sokol/c/sokol_shape.c',
|
||||
}
|
||||
|
||||
func_name_ignores = [
|
||||
c_callbacks = [
|
||||
'slog_func',
|
||||
]
|
||||
|
||||
ignores = [
|
||||
'sdtx_printf',
|
||||
'sdtx_vprintf',
|
||||
]
|
||||
|
||||
func_name_overrides = {
|
||||
'sgl_error': 'sgl_get_error', # 'error' is reserved in Zig
|
||||
'sgl_deg': 'sgl_as_degrees',
|
||||
'sgl_rad': 'sgl_as_radians',
|
||||
}
|
||||
|
||||
struct_field_type_overrides = {
|
||||
overrides = {
|
||||
'sgl_error': 'sgl_get_error',
|
||||
'sgl_deg': 'sgl_as_degrees',
|
||||
'sgl_rad': 'sgl_as_radians',
|
||||
'sg_context_desc.color_format': 'int',
|
||||
'sg_context_desc.depth_format': 'int',
|
||||
'SGL_NO_ERROR': 'SGL_ERROR_NO_ERROR',
|
||||
'SG_BUFFERTYPE_VERTEXBUFFER': 'SG_BUFFERTYPE_VERTEX_BUFFER',
|
||||
'SG_BUFFERTYPE_INDEXBUFFER': 'SG_BUFFERTYPE_INDEX_BUFFER',
|
||||
'SG_ACTION_DONTCARE': 'SG_ACTION_DONT_CARE',
|
||||
'ptr': 'addr', # range ptr
|
||||
'func': 'fn',
|
||||
'slog_func': 'fn',
|
||||
}
|
||||
|
||||
enumPrefixOverrides = {
|
||||
# sokol_gfx.h
|
||||
'PIXELFORMAT': 'pixelFormat',
|
||||
'RESOURCESTATE': 'resourceState',
|
||||
'BUFFERTYPE': 'bufferType',
|
||||
'INDEXTYPE': 'indexType',
|
||||
'IMAGETYPE': 'imageType',
|
||||
'SAMPLERTYPE': 'samplerType',
|
||||
'CUBEFACE': 'cubeFace',
|
||||
'SHADERSTAGE': 'shaderStage',
|
||||
'PRIMITIVETYPE': 'primitiveType',
|
||||
'BORDERCOLOR': 'borderColor',
|
||||
'VERTEXFORMAT': 'vertexFormat',
|
||||
'VERTEXSTEP': 'vertexStep',
|
||||
'UNIFORMTYPE': 'uniformType',
|
||||
'UNIFORMLAYOUT': 'uniformLayout',
|
||||
'CULLMODE': 'cullMode',
|
||||
'FACEWINDING': 'faceWinding',
|
||||
'COMPAREFUNC': 'compareFunc',
|
||||
'STENCILOP': 'stencilOp',
|
||||
'BLENDFACTOR': 'blendFactor',
|
||||
'BLENDOP': 'blendOp',
|
||||
'COLORMASK': 'colorMask',
|
||||
# sokol_app.h
|
||||
'EVENTTYPE': 'eventType',
|
||||
'KEYCODE': 'keyCode',
|
||||
'MOUSEBUTTON': 'mouseButton',
|
||||
}
|
||||
|
||||
prim_types = {
|
||||
@@ -60,7 +102,7 @@ prim_types = {
|
||||
'double': 'float64',
|
||||
'uintptr_t': 'uint',
|
||||
'intptr_t': 'int',
|
||||
'size_t': 'int',
|
||||
'size_t': 'int', # not a bug, Nim's sizeof() returns int
|
||||
}
|
||||
|
||||
prim_defaults = {
|
||||
@@ -74,31 +116,62 @@ prim_defaults = {
|
||||
'uint32_t': '0',
|
||||
'int64_t': '0',
|
||||
'uint64_t': '0',
|
||||
'float': '0.0',
|
||||
'float': '0.0f',
|
||||
'double': '0.0',
|
||||
'uintptr_t': '0',
|
||||
'intptr_t': '0',
|
||||
'size_t': '0'
|
||||
}
|
||||
|
||||
common_prim_types = """
|
||||
array
|
||||
untyped typed void
|
||||
bool byte char
|
||||
int int8 int16 int32 int64
|
||||
uint uint8 uint16 uint32 uint64
|
||||
float float32 float64
|
||||
string
|
||||
cchar cint csize_t
|
||||
cfloat cdouble
|
||||
cstring
|
||||
pointer
|
||||
""".split()
|
||||
|
||||
keywords = """
|
||||
addr and as asm
|
||||
bind block break
|
||||
case cast concept const continue converter
|
||||
defer discard distinct div do
|
||||
elif else end enum except export
|
||||
finally for from func
|
||||
if import in include interface is isnot iterator
|
||||
let
|
||||
macro method mixin mod
|
||||
nil not notin
|
||||
object of or out
|
||||
proc ptr
|
||||
raise ref return
|
||||
shl shr static
|
||||
template try tuple type
|
||||
using
|
||||
var
|
||||
when while
|
||||
xor
|
||||
yield
|
||||
""".split() + common_prim_types
|
||||
|
||||
struct_types = []
|
||||
enum_types = []
|
||||
enum_items = {}
|
||||
out_lines = ''
|
||||
|
||||
def reset_globals():
|
||||
global struct_types
|
||||
global enum_types
|
||||
global enum_items
|
||||
global out_lines
|
||||
struct_types = []
|
||||
enum_types = []
|
||||
enum_items = {}
|
||||
out_lines = ''
|
||||
|
||||
re_1d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]$")
|
||||
re_2d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]\[\d*\]$")
|
||||
|
||||
def l(s):
|
||||
global out_lines
|
||||
out_lines += s + '\n'
|
||||
@@ -107,90 +180,66 @@ def as_nim_prim_type(s):
|
||||
return prim_types[s]
|
||||
|
||||
# prefix_bla_blub(_t) => (dep.)BlaBlub
|
||||
def as_nim_struct_type(s, prefix):
|
||||
def as_nim_type_name(s, prefix):
|
||||
parts = s.lower().split('_')
|
||||
outp = '' if s.startswith(prefix) else f'{parts[0]}.'
|
||||
dep = parts[0] + '_'
|
||||
outp = ''
|
||||
if not s.startswith(prefix) and dep in module_names:
|
||||
outp = module_names[dep] + '.'
|
||||
for part in parts[1:]:
|
||||
# ignore '_t' type postfix
|
||||
if (part != 't'):
|
||||
outp += part.capitalize()
|
||||
return outp
|
||||
|
||||
# prefix_bla_blub(_t) => (dep.)BlaBlub
|
||||
def as_nim_enum_type(s, prefix):
|
||||
parts = s.lower().split('_')
|
||||
outp = '' if s.startswith(prefix) else f'{parts[0]}.'
|
||||
for part in parts[1:]:
|
||||
if (part != 't'):
|
||||
outp += part.capitalize()
|
||||
return outp
|
||||
|
||||
# prefix_bla_blub(_t) => (dep.)BlaBlub
|
||||
def as_nim_const_type(s, prefix):
|
||||
parts = s.lower().split('_')
|
||||
outp = '' if s.startswith(prefix) else f'{parts[0]}.'
|
||||
for part in parts[1:]:
|
||||
if (part != 't'):
|
||||
outp += part.capitalize()
|
||||
return outp
|
||||
|
||||
def check_struct_field_type_override(struct_name, field_name, orig_type):
|
||||
s = f"{struct_name}.{field_name}"
|
||||
if s in struct_field_type_overrides:
|
||||
return struct_field_type_overrides[s]
|
||||
def check_override(name, default=None):
|
||||
if name in overrides:
|
||||
return overrides[name]
|
||||
elif default is None:
|
||||
return name
|
||||
else:
|
||||
return orig_type
|
||||
return default
|
||||
|
||||
def check_func_name_ignore(func_name):
|
||||
return func_name in func_name_ignores
|
||||
def check_ignore(name):
|
||||
return name in ignores
|
||||
|
||||
def check_func_name_override(func_name):
|
||||
if func_name in func_name_overrides:
|
||||
return func_name_overrides[func_name]
|
||||
def is_power_of_two(val):
|
||||
return val == 0 or val & (val - 1) == 0
|
||||
|
||||
def wrap_keywords(s):
|
||||
if s in keywords:
|
||||
return f'`{s}`'
|
||||
else:
|
||||
return func_name
|
||||
|
||||
def trim_prefix(s, prefix):
|
||||
outp = s;
|
||||
if outp.lower().startswith(prefix.lower()):
|
||||
outp = outp[len(prefix):]
|
||||
return outp
|
||||
|
||||
# PREFIX_BLA_BLUB to bla_blub
|
||||
def as_snake_case(s, prefix = ""):
|
||||
return trim_prefix(s, prefix).lower()
|
||||
return s
|
||||
|
||||
# prefix_bla_blub => blaBlub
|
||||
def as_camel_case(s, prefix = ""):
|
||||
parts = trim_prefix(s, prefix).lower().split('_')
|
||||
def as_camel_case(s, prefix, wrap=True):
|
||||
outp = s.lower()
|
||||
if outp.startswith(prefix):
|
||||
outp = outp[len(prefix):]
|
||||
parts = outp.lstrip('_').split('_')
|
||||
outp = parts[0]
|
||||
for part in parts[1:]:
|
||||
outp += part.capitalize()
|
||||
if wrap:
|
||||
outp = wrap_keywords(outp)
|
||||
return outp
|
||||
|
||||
# prefix_bla_blub => BlaBlub
|
||||
def as_pascal_case(s, prefix):
|
||||
parts = trim_prefix(s, prefix).lower().split('_')
|
||||
outp = ""
|
||||
for part in parts:
|
||||
# PREFIX_ENUM_BLA_BLO => blaBlo
|
||||
def as_enum_item_name(s, wrap=True):
|
||||
outp = s.lstrip('_')
|
||||
parts = outp.split('_')[1:]
|
||||
if parts[0] in enumPrefixOverrides:
|
||||
parts[0] = enumPrefixOverrides[parts[0]]
|
||||
else:
|
||||
parts[0] = parts[0].lower()
|
||||
outp = parts[0]
|
||||
for part in parts[1:]:
|
||||
outp += part.capitalize()
|
||||
if wrap:
|
||||
outp = wrap_keywords(outp)
|
||||
return outp
|
||||
|
||||
# PREFIX_ENUM_BLA => Bla, _PREFIX_ENUM_BLA => Bla
|
||||
def as_enum_item_name(s):
|
||||
outp = s
|
||||
if outp.startswith('_'):
|
||||
outp = outp[1:]
|
||||
parts = outp.lower().split('_')[2:]
|
||||
outp = ""
|
||||
for part in parts:
|
||||
outp += part.capitalize()
|
||||
if outp[0].isdigit():
|
||||
outp = 'N' + outp
|
||||
return outp
|
||||
|
||||
def enum_default_item(enum_name):
|
||||
return enum_items[enum_name][0]
|
||||
|
||||
def is_prim_type(s):
|
||||
return s in prim_types
|
||||
|
||||
@@ -200,15 +249,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} *":
|
||||
@@ -227,266 +267,208 @@ 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)
|
||||
|
||||
def is_2d_array_type(s):
|
||||
return re_2d_array.match(s)
|
||||
|
||||
def type_default_value(s):
|
||||
return prim_defaults[s]
|
||||
|
||||
def extract_array_type(s):
|
||||
return s[:s.index('[')].strip()
|
||||
|
||||
def extract_array_nums(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_extern_c_arg_type(arg_type, prefix):
|
||||
if arg_type == "void":
|
||||
return "void"
|
||||
elif is_prim_type(arg_type):
|
||||
return as_nim_prim_type(arg_type)
|
||||
elif is_struct_type(arg_type):
|
||||
return as_nim_struct_type(arg_type, prefix)
|
||||
elif is_enum_type(arg_type):
|
||||
return as_nim_enum_type(arg_type, prefix)
|
||||
elif is_void_ptr(arg_type):
|
||||
return "pointer"
|
||||
elif is_const_void_ptr(arg_type):
|
||||
return "pointer"
|
||||
elif is_string_ptr(arg_type):
|
||||
return "cstring"
|
||||
elif is_const_struct_ptr(arg_type):
|
||||
return f"ptr {as_nim_struct_type(extract_ptr_type(arg_type), prefix)}"
|
||||
elif is_prim_ptr(arg_type):
|
||||
return f"[*c] {as_nim_prim_type(extract_ptr_type(arg_type))}"
|
||||
elif is_const_prim_ptr(arg_type):
|
||||
return f"ptr {as_nim_prim_type(extract_ptr_type(arg_type))}"
|
||||
else:
|
||||
return '??? (as_extern_c_arg_type)'
|
||||
|
||||
def as_nim_arg_type(arg_prefix, arg_type, prefix):
|
||||
# NOTE: if arg_prefix is None, the result is used as return value
|
||||
pre = "" if arg_prefix is None else arg_prefix
|
||||
if arg_type == "void":
|
||||
if arg_prefix is None:
|
||||
return "void"
|
||||
else:
|
||||
return ""
|
||||
elif is_prim_type(arg_type):
|
||||
return pre + as_nim_prim_type(arg_type)
|
||||
elif is_struct_type(arg_type):
|
||||
return pre + as_nim_struct_type(arg_type, prefix)
|
||||
elif is_enum_type(arg_type):
|
||||
return pre + as_nim_enum_type(arg_type, prefix)
|
||||
elif is_void_ptr(arg_type):
|
||||
return pre + "pointer"
|
||||
elif is_const_void_ptr(arg_type):
|
||||
return pre + "pointer"
|
||||
elif is_string_ptr(arg_type):
|
||||
return pre + "cstring"
|
||||
elif is_const_struct_ptr(arg_type):
|
||||
return pre + f"ptr {as_nim_struct_type(extract_ptr_type(arg_type), prefix)}"
|
||||
elif is_prim_ptr(arg_type):
|
||||
return pre + f"ptr {as_nim_prim_type(extract_ptr_type(arg_type))}"
|
||||
elif is_const_prim_ptr(arg_type):
|
||||
return pre + f"ptr {as_nim_prim_type(extract_ptr_type(arg_type))}"
|
||||
else:
|
||||
return arg_prefix + "??? (as_nim_arg_type)"
|
||||
|
||||
# get C-style arguments of a function pointer as string
|
||||
def funcptr_args_c(field_type, prefix):
|
||||
def funcptr_args(field_type, prefix):
|
||||
tokens = field_type[field_type.index('(*)')+4:-1].split(',')
|
||||
s = ""
|
||||
n = 0
|
||||
for token in tokens:
|
||||
n += 1
|
||||
arg_type = token.strip()
|
||||
arg_ctype = token.strip()
|
||||
if s != "":
|
||||
s += ", "
|
||||
c_arg = f"a{n}:" + as_extern_c_arg_type(arg_type, prefix)
|
||||
if (c_arg == "void"):
|
||||
return ""
|
||||
else:
|
||||
s += c_arg
|
||||
arg_nimtype = as_nim_type(arg_ctype, prefix)
|
||||
if arg_nimtype == "":
|
||||
return "" # fun(void)
|
||||
s += f"a{n}:{arg_nimtype}"
|
||||
if s == "a1:void":
|
||||
s = ""
|
||||
return s
|
||||
|
||||
# get C-style result of a function pointer as string
|
||||
def funcptr_res_c(field_type):
|
||||
res_type = field_type[:field_type.index('(*)')].strip()
|
||||
if res_type == 'void':
|
||||
return ''
|
||||
elif is_const_void_ptr(res_type):
|
||||
return ':pointer'
|
||||
else:
|
||||
return '???'
|
||||
def funcptr_result(field_type, prefix):
|
||||
ctype = field_type[:field_type.index('(*)')].strip()
|
||||
return as_nim_type(ctype, prefix)
|
||||
|
||||
def funcdecl_args_c(decl, prefix):
|
||||
s = ""
|
||||
for param_decl in decl['params']:
|
||||
if s != "":
|
||||
s += ", "
|
||||
arg_type = param_decl['type']
|
||||
s += as_extern_c_arg_type(arg_type, prefix)
|
||||
return s
|
||||
|
||||
def funcdecl_args_nim(decl, prefix):
|
||||
s = ""
|
||||
for param_decl in decl['params']:
|
||||
if s != "":
|
||||
s += ", "
|
||||
arg_name = param_decl['name']
|
||||
arg_type = param_decl['type']
|
||||
s += f"{as_nim_arg_type(f'{arg_name}:', arg_type, prefix)}"
|
||||
return s
|
||||
|
||||
def funcdecl_res_c(decl, prefix):
|
||||
decl_type = decl['type']
|
||||
res_type = decl_type[:decl_type.index('(')].strip()
|
||||
return as_extern_c_arg_type(res_type, prefix)
|
||||
|
||||
def funcdecl_res_nim(decl, prefix):
|
||||
decl_type = decl['type']
|
||||
res_type = decl_type[:decl_type.index('(')].strip()
|
||||
nim_res_type = as_nim_arg_type(None, res_type, prefix)
|
||||
if nim_res_type == "":
|
||||
nim_res_type = "void"
|
||||
return nim_res_type
|
||||
|
||||
def gen_struct(decl, prefix, use_raw_name=False):
|
||||
struct_name = decl['name']
|
||||
nim_type = struct_name if use_raw_name else as_nim_struct_type(struct_name, prefix)
|
||||
l(f"type {nim_type}* = object")
|
||||
isPublic = True
|
||||
for field in decl['fields']:
|
||||
field_name = field['name']
|
||||
if field_name == "__pad":
|
||||
# FIXME: these should be guarded by SOKOL_ZIG_BINDINGS, but aren't?
|
||||
continue
|
||||
isPublic = not field_name.startswith("_")
|
||||
field_name = as_camel_case(field_name, "_")
|
||||
if field_name == "ptr":
|
||||
field_name = "source"
|
||||
if field_name == "ref":
|
||||
field_name = "`ref`"
|
||||
if field_name == "type":
|
||||
field_name = "`type`"
|
||||
if isPublic:
|
||||
field_name += "*"
|
||||
field_type = field['type']
|
||||
field_type = check_struct_field_type_override(struct_name, field_name, field_type)
|
||||
if is_prim_type(field_type):
|
||||
l(f" {field_name}:{as_nim_prim_type(field_type)}")
|
||||
elif is_struct_type(field_type):
|
||||
l(f" {field_name}:{as_nim_struct_type(field_type, prefix)}")
|
||||
elif is_enum_type(field_type):
|
||||
l(f" {field_name}:{as_nim_enum_type(field_type, prefix)}")
|
||||
elif is_string_ptr(field_type):
|
||||
l(f" {field_name}:cstring")
|
||||
elif is_const_void_ptr(field_type):
|
||||
l(f" {field_name}:pointer")
|
||||
elif is_void_ptr(field_type):
|
||||
l(f" {field_name}:pointer")
|
||||
elif is_const_prim_ptr(field_type):
|
||||
l(f" {field_name}:ptr {as_nim_prim_type(extract_ptr_type(field_type))}")
|
||||
elif is_func_ptr(field_type):
|
||||
l(f" {field_name}:proc({funcptr_args_c(field_type, prefix)}){funcptr_res_c(field_type)} {{.cdecl.}}")
|
||||
elif is_1d_array_type(field_type):
|
||||
array_type = extract_array_type(field_type)
|
||||
array_nums = extract_array_nums(field_type)
|
||||
if is_prim_type(array_type) or is_struct_type(array_type):
|
||||
if is_prim_type(array_type):
|
||||
nim_type = as_nim_prim_type(array_type)
|
||||
elif is_struct_type(array_type):
|
||||
nim_type = as_nim_struct_type(array_type, prefix)
|
||||
elif is_enum_type(array_type):
|
||||
nim_type = as_nim_enum_type(array_type, prefix)
|
||||
else:
|
||||
nim_type = '??? (array type)'
|
||||
t0 = f"array[{array_nums[0]}, {nim_type}]"
|
||||
t0_slice = f"[]const {nim_type}"
|
||||
t1 = f"[_]{nim_type}"
|
||||
l(f" {field_name}:{t0}")
|
||||
elif is_const_void_ptr(array_type):
|
||||
l(f" {field_name}:array[{array_nums[0]}, pointer]")
|
||||
else:
|
||||
l(f"// FIXME: ??? array {field_name}:{field_type} => {array_type} [{array_nums[0]}]")
|
||||
elif is_2d_array_type(field_type):
|
||||
array_type = extract_array_type(field_type)
|
||||
array_nums = extract_array_nums(field_type)
|
||||
if is_prim_type(array_type):
|
||||
nim_type = as_nim_prim_type(array_type)
|
||||
def_val = type_default_value(array_type)
|
||||
elif is_struct_type(array_type):
|
||||
nim_type = as_nim_struct_type(array_type, prefix)
|
||||
def_val = ".{ }"
|
||||
else:
|
||||
nim_type = "???"
|
||||
def_val = "???"
|
||||
t0 = f"array[{array_nums[0]}, array[{array_nums[1]}, {nim_type}]]"
|
||||
l(f" {field_name}:{t0}")
|
||||
def as_nim_type(ctype, prefix, struct_ptr_as_value=False):
|
||||
if ctype == "void":
|
||||
return ""
|
||||
elif is_prim_type(ctype):
|
||||
return as_nim_prim_type(ctype)
|
||||
elif is_struct_type(ctype):
|
||||
return as_nim_type_name(ctype, prefix)
|
||||
elif is_enum_type(ctype):
|
||||
return as_nim_type_name(ctype, prefix)
|
||||
elif util.is_string_ptr(ctype):
|
||||
return "cstring"
|
||||
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(util.extract_ptr_type(ctype), prefix)
|
||||
if struct_ptr_as_value:
|
||||
return f"{nim_type}"
|
||||
else:
|
||||
l(f"// FIXME: {field_name}:{field_type};")
|
||||
return f"ptr {nim_type}"
|
||||
elif is_prim_ptr(ctype) or is_const_prim_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 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 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}")
|
||||
|
||||
def as_nim_struct_name(struct_decl, prefix):
|
||||
struct_name = check_override(struct_decl['name'])
|
||||
nim_type = f'{as_nim_type_name(struct_name, prefix)}'
|
||||
return nim_type
|
||||
|
||||
def as_nim_field_name(field_decl, prefix, check_private=True):
|
||||
field_name = as_camel_case(check_override(field_decl['name']), prefix)
|
||||
if check_private:
|
||||
is_private = field_decl['name'].startswith('_')
|
||||
if not is_private:
|
||||
field_name += "*"
|
||||
return field_name
|
||||
|
||||
def as_nim_field_type(struct_decl, field_decl, prefix):
|
||||
return as_nim_type(check_override(f"{struct_decl['name']}.{field_decl['name']}", default=field_decl['type']), prefix)
|
||||
|
||||
def gen_struct(decl, prefix):
|
||||
l(f"type {as_nim_struct_name(decl, prefix)}* = object")
|
||||
for field in decl['fields']:
|
||||
l(f" {as_nim_field_name(field, prefix)}:{as_nim_field_type(decl, field, prefix)}")
|
||||
l("")
|
||||
|
||||
def gen_consts(decl, prefix):
|
||||
l("const")
|
||||
for item in decl['items']:
|
||||
l(f" {trim_prefix(item['name'], prefix)}* = {item['value']}")
|
||||
item_name = check_override(item['name'])
|
||||
l(f" {as_camel_case(item_name, prefix)}* = {item['value']}")
|
||||
l("")
|
||||
|
||||
def gen_enum(decl, prefix):
|
||||
item_names_by_value = {}
|
||||
value = -1
|
||||
hasForceU32 = False
|
||||
hasExplicitValues = False
|
||||
has_explicit_values = False
|
||||
for item in decl['items']:
|
||||
itemName = item['name']
|
||||
if itemName.endswith("_FORCE_U32"):
|
||||
hasForceU32 = True
|
||||
elif itemName.endswith("_NUM"):
|
||||
item_name = check_override(item['name'])
|
||||
if item_name.endswith("_NUM") or item_name.endswith("_FORCE_U32"):
|
||||
continue
|
||||
else:
|
||||
if 'value' in item:
|
||||
hasExplicitValues = True
|
||||
has_explicit_values = True
|
||||
value = int(item['value'])
|
||||
else:
|
||||
value += 1
|
||||
item_names_by_value[value] = as_enum_item_name(item['name']);
|
||||
if hasForceU32:
|
||||
l(f"type {as_nim_enum_type(decl['name'], prefix)}* {{.pure, size:4.}} = enum")
|
||||
else:
|
||||
l(f"type {as_nim_enum_type(decl['name'], prefix)}* {{.pure.}} = enum")
|
||||
if hasExplicitValues:
|
||||
item_names_by_value[value] = as_enum_item_name(item_name)
|
||||
enum_name_nim = as_nim_type_name(decl['name'], prefix)
|
||||
l('type')
|
||||
l(f" {enum_name_nim}* {{.size:sizeof(int32).}} = enum")
|
||||
if has_explicit_values:
|
||||
# Nim requires explicit enum values to be declared in ascending order
|
||||
for value in sorted(item_names_by_value):
|
||||
name = item_names_by_value[value]
|
||||
l(f" {name} = {value},")
|
||||
l(f" {name} = {value},")
|
||||
else:
|
||||
for name in item_names_by_value.values():
|
||||
l(f" {name},")
|
||||
l(f" {name},")
|
||||
l("")
|
||||
|
||||
# returns C prototype compatible function args (with pointers)
|
||||
def funcdecl_args_c(decl, prefix):
|
||||
s = ""
|
||||
func_name = decl['name']
|
||||
for param_decl in decl['params']:
|
||||
if s != "":
|
||||
s += ", "
|
||||
arg_name = param_decl['name']
|
||||
arg_type = check_override(f'{func_name}.{arg_name}', default=param_decl['type'])
|
||||
s += f"{as_camel_case(arg_name, prefix)}:{as_nim_type(arg_type, prefix)}"
|
||||
return s
|
||||
|
||||
# returns Nim function args (pass structs by value)
|
||||
def funcdecl_args_nim(decl, prefix):
|
||||
s = ""
|
||||
func_name = decl['name']
|
||||
for param_decl in decl['params']:
|
||||
if s != "":
|
||||
s += ", "
|
||||
arg_name = param_decl['name']
|
||||
arg_type = check_override(f'{func_name}.{arg_name}', default=param_decl['type'])
|
||||
s += f"{as_camel_case(arg_name, prefix)}:{as_nim_type(arg_type, prefix, struct_ptr_as_value=True)}"
|
||||
return s
|
||||
|
||||
def funcdecl_result(decl, prefix):
|
||||
func_name = decl['name']
|
||||
decl_type = decl['type']
|
||||
result_type = check_override(f'{func_name}.RESULT', default=decl_type[:decl_type.index('(')].strip())
|
||||
nim_res_type = as_nim_type(result_type, prefix)
|
||||
if nim_res_type == "":
|
||||
nim_res_type = "void"
|
||||
return nim_res_type
|
||||
|
||||
def gen_func_nim(decl, prefix):
|
||||
c_func_name = decl['name']
|
||||
nim_func_name = as_camel_case(decl['name'], prefix)
|
||||
nim_res_type = funcdecl_res_nim(decl, prefix)
|
||||
l(f"proc {nim_func_name}*({funcdecl_args_nim(decl, prefix)}):{funcdecl_res_nim(decl, prefix)} {{.cdecl, importc:\"{decl['name']}\".}}")
|
||||
nim_func_name = as_camel_case(check_override(c_func_name), prefix, wrap=False)
|
||||
nim_res_type = funcdecl_result(decl, prefix)
|
||||
if c_func_name in c_callbacks:
|
||||
l(f"proc {nim_func_name}*({funcdecl_args_c(decl, prefix)}):{nim_res_type} {{.cdecl, importc:\"{c_func_name}\".}}")
|
||||
else:
|
||||
l(f"proc c_{nim_func_name}({funcdecl_args_c(decl, prefix)}):{nim_res_type} {{.cdecl, importc:\"{c_func_name}\".}}")
|
||||
l(f"proc {wrap_keywords(nim_func_name)}*({funcdecl_args_nim(decl, prefix)}):{nim_res_type} =")
|
||||
s = f" c_{nim_func_name}("
|
||||
for i, param_decl in enumerate(decl['params']):
|
||||
if i > 0:
|
||||
s += ", "
|
||||
arg_name = param_decl['name']
|
||||
arg_type = param_decl['type']
|
||||
if is_const_struct_ptr(arg_type):
|
||||
s += f"unsafeAddr({arg_name})"
|
||||
else:
|
||||
s += arg_name
|
||||
s += ")"
|
||||
l(s)
|
||||
l("")
|
||||
|
||||
def gen_array_converters(decl, prefix):
|
||||
for field in decl['fields']:
|
||||
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 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 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}]] =')
|
||||
l(f' static: assert(X < {x})')
|
||||
l(f' static: assert(Y < {y})')
|
||||
l(f' for indexY,itemY in items.pairs:')
|
||||
l(f' for indexX, itemX in itemY.pairs:')
|
||||
l(f' result[indexY][indexX] = itemX')
|
||||
l('')
|
||||
else:
|
||||
sys.exit('Unsupported converter array dimension (> 2)!')
|
||||
|
||||
def pre_parse(inp):
|
||||
global struct_types
|
||||
global enum_types
|
||||
@@ -497,15 +479,92 @@ def pre_parse(inp):
|
||||
elif kind == 'enum':
|
||||
enum_name = decl['name']
|
||||
enum_types.append(enum_name)
|
||||
enum_items[enum_name] = []
|
||||
for item in decl['items']:
|
||||
enum_items[enum_name].append(as_enum_item_name(item['name']))
|
||||
|
||||
def gen_imports(inp, dep_prefixes):
|
||||
for dep_prefix in dep_prefixes:
|
||||
dep_module_name = module_names[dep_prefix]
|
||||
l(f'import {dep_module_name}')
|
||||
l('')
|
||||
|
||||
def gen_extra(inp):
|
||||
if inp['prefix'] in ['sg_']:
|
||||
# FIXME: remove when sokol-shdc has been integrated!
|
||||
l('when defined gl:')
|
||||
l(' const gl* = true')
|
||||
l(' const d3d11* = false')
|
||||
l(' const metal* = false')
|
||||
l('elif defined windows:')
|
||||
l(' const gl* = false')
|
||||
l(' const d3d11* = true')
|
||||
l(' const metal* = false')
|
||||
l('elif defined macosx:')
|
||||
l(' const gl* = false')
|
||||
l(' const d3d11* = false')
|
||||
l(' const metal* = true')
|
||||
l('elif defined linux:')
|
||||
l(' const gl* = true')
|
||||
l(' const d3d11* = false')
|
||||
l(' const metal* = false')
|
||||
l('else:')
|
||||
l(' error("unsupported platform")')
|
||||
l('')
|
||||
if inp['prefix'] in ['sg_', 'sapp_']:
|
||||
l('when defined windows:')
|
||||
l(' when not defined vcc:')
|
||||
l(' {.passl:"-lkernel32 -luser32 -lshell32 -lgdi32".}')
|
||||
l(' when defined gl:')
|
||||
l(' {.passc:"-DSOKOL_GLCORE33".}')
|
||||
l(' else:')
|
||||
l(' {.passc:"-DSOKOL_D3D11".}')
|
||||
l(' when not defined vcc:')
|
||||
l(' {.passl:"-ld3d11 -ldxgi".}')
|
||||
l('elif defined macosx:')
|
||||
l(' {.passc:"-x objective-c".}')
|
||||
l(' {.passl:"-framework Cocoa -framework QuartzCore".}')
|
||||
l(' when defined gl:')
|
||||
l(' {.passc:"-DSOKOL_GLCORE33".}')
|
||||
l(' {.passl:"-framework OpenGL".}')
|
||||
l(' else:')
|
||||
l(' {.passc:"-DSOKOL_METAL".}')
|
||||
l(' {.passl:"-framework Metal -framework MetalKit".}')
|
||||
l('elif defined linux:')
|
||||
l(' {.passc:"-DSOKOL_GLCORE33".}')
|
||||
l(' {.passl:"-lX11 -lXi -lXcursor -lGL -lm -ldl -lpthread".}')
|
||||
l('else:')
|
||||
l(' error("unsupported platform")')
|
||||
l('')
|
||||
if inp['prefix'] in ['saudio_']:
|
||||
l('when defined windows:')
|
||||
l(' when not defined vcc:')
|
||||
l(' {.passl:"-lkernel32 -lole32".}')
|
||||
l('elif defined macosx:')
|
||||
l(' {.passl:"-framework AudioToolbox".}')
|
||||
l('elif defined linux:')
|
||||
l(' {.passl:"-lasound -lm -lpthread".}')
|
||||
l('else:')
|
||||
l(' error("unsupported platform")')
|
||||
l('')
|
||||
if inp['prefix'] in ['sg_']:
|
||||
l('## Convert a 4-element tuple of numbers to a gfx.Color')
|
||||
l('converter toColor*[R:SomeNumber,G:SomeNumber,B:SomeNumber,A:SomeNumber](rgba: tuple [r:R,g:G,b:B,a:A]):Color =')
|
||||
l(' Color(r:rgba.r.float32, g:rgba.g.float32, b:rgba.b.float32, a:rgba.a.float32)')
|
||||
l('')
|
||||
l('## Convert a 3-element tuple of numbers to a gfx.Color')
|
||||
l('converter toColor*[R:SomeNumber,G:SomeNumber,B:SomeNumber](rgba: tuple [r:R,g:G,b:B]):Color =')
|
||||
l(' Color(r:rgba.r.float32, g:rgba.g.float32, b:rgba.b.float32, a:1.float32)')
|
||||
l('')
|
||||
# NOTE: this simplistic to_Range() converter has various issues, some of them dangerous:
|
||||
# - doesn't work as expected for slice types
|
||||
# - it's very easy to create a range that points to invalid memory
|
||||
# (so far observed for stack-allocated structs <= 16 bytes)
|
||||
#if inp['prefix'] in ['sg_', 'sdtx_', 'sshape_']:
|
||||
# l('# helper function to convert "anything" into a Range')
|
||||
# l('converter to_Range*[T](source: T): Range =')
|
||||
# l(' Range(addr: source.unsafeAddr, size: source.sizeof.uint)')
|
||||
# l('')
|
||||
c_source_path = '/'.join(c_source_paths[inp['prefix']].split('/')[3:])
|
||||
l('{.passc:"-DSOKOL_NIM_IMPL".}')
|
||||
l(f'{{.compile:"{c_source_path}".}}')
|
||||
|
||||
def gen_module(inp, dep_prefixes):
|
||||
l('## machine generated, do not edit')
|
||||
@@ -518,22 +577,27 @@ def gen_module(inp, dep_prefixes):
|
||||
kind = decl['kind']
|
||||
if kind == 'consts':
|
||||
gen_consts(decl, prefix)
|
||||
elif kind == 'enum':
|
||||
gen_enum(decl, prefix)
|
||||
elif kind == 'struct':
|
||||
gen_struct(decl, prefix)
|
||||
elif kind == 'func':
|
||||
if not check_func_name_ignore(decl['name']):
|
||||
elif not check_ignore(decl['name']):
|
||||
if kind == 'struct':
|
||||
gen_struct(decl, prefix)
|
||||
gen_array_converters(decl, prefix)
|
||||
elif kind == 'enum':
|
||||
gen_enum(decl, prefix)
|
||||
elif kind == 'func':
|
||||
gen_func_nim(decl, prefix)
|
||||
gen_extra(inp)
|
||||
|
||||
def prepare():
|
||||
print('Generating nim bindings:')
|
||||
print('=== Generating Nim bindings:')
|
||||
if not os.path.isdir('sokol-nim/src/sokol'):
|
||||
os.makedirs('sokol-nim/src/sokol')
|
||||
if not os.path.isdir('sokol-nim/src/sokol/c'):
|
||||
os.makedirs('sokol-nim/src/sokol/c')
|
||||
|
||||
def gen(c_header_path, c_prefix, dep_c_prefixes):
|
||||
if not c_prefix in module_names:
|
||||
print(f' >> warning: skipping generation for {c_prefix} prefix...')
|
||||
return
|
||||
global out_lines
|
||||
module_name = module_names[c_prefix]
|
||||
c_source_path = c_source_paths[c_prefix]
|
||||
@@ -543,20 +607,5 @@ def gen(c_header_path, c_prefix, dep_c_prefixes):
|
||||
ir = gen_ir.gen(c_header_path, c_source_path, module_name, c_prefix, dep_c_prefixes)
|
||||
gen_module(ir, dep_c_prefixes)
|
||||
output_path = f"sokol-nim/src/sokol/{ir['module']}.nim"
|
||||
|
||||
## some changes for readability
|
||||
out_lines = out_lines.replace("PixelformatInfo", "PixelFormatInfo")
|
||||
out_lines = out_lines.replace(" Dontcare,", " DontCare,")
|
||||
out_lines = out_lines.replace(" Vertexbuffer,", " VertexBuffer,")
|
||||
out_lines = out_lines.replace(" Indexbuffer,", " IndexBuffer,")
|
||||
out_lines = out_lines.replace(" N2d,", " Plane,")
|
||||
out_lines = out_lines.replace(" N3d,", " Volume,")
|
||||
out_lines = out_lines.replace(" Vs,", " Vertex,")
|
||||
out_lines = out_lines.replace(" Fs,", " Fragment,")
|
||||
|
||||
## include extensions in generated code
|
||||
l("# Nim-specific API extensions")
|
||||
l(f"include nim/{ir['module']}")
|
||||
|
||||
with open(output_path, 'w', newline='\n') as f_outp:
|
||||
f_outp.write(out_lines)
|
||||
|
||||
Vendored
+138
-170
@@ -1,5 +1,5 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# Read output of gen_json.py and generate Zig language bindings.
|
||||
# Generate Zig bindings.
|
||||
#
|
||||
# Zig coding style:
|
||||
# - types are PascalCase
|
||||
@@ -7,9 +7,12 @@
|
||||
# - otherwise snake_case
|
||||
#-------------------------------------------------------------------------------
|
||||
import gen_ir
|
||||
import json, re, os, shutil
|
||||
import os, shutil, sys
|
||||
|
||||
import gen_util as util
|
||||
|
||||
module_names = {
|
||||
'slog_': 'log',
|
||||
'sg_': 'gfx',
|
||||
'sapp_': 'app',
|
||||
'stm_': 'time',
|
||||
@@ -20,6 +23,7 @@ module_names = {
|
||||
}
|
||||
|
||||
c_source_paths = {
|
||||
'slog_': 'sokol-zig/src/sokol/c/sokol_log.c',
|
||||
'sg_': 'sokol-zig/src/sokol/c/sokol_gfx.c',
|
||||
'sapp_': 'sokol-zig/src/sokol/c/sokol_app.c',
|
||||
'stm_': 'sokol-zig/src/sokol/c/sokol_time.c',
|
||||
@@ -29,21 +33,23 @@ c_source_paths = {
|
||||
'sshape_': 'sokol-zig/src/sokol/c/sokol_shape.c',
|
||||
}
|
||||
|
||||
name_ignores = [
|
||||
ignores = [
|
||||
'sdtx_printf',
|
||||
'sdtx_vprintf',
|
||||
'sg_install_trace_hooks',
|
||||
'sg_trace_hooks',
|
||||
]
|
||||
|
||||
name_overrides = {
|
||||
'sgl_error': 'sgl_get_error', # 'error' is reserved in Zig
|
||||
'sgl_deg': 'sgl_as_degrees',
|
||||
'sgl_rad': 'sgl_as_radians'
|
||||
}
|
||||
# functions that need to be exposed as 'raw' C callbacks without a Zig wrapper function
|
||||
c_callbacks = [
|
||||
'slog_func'
|
||||
]
|
||||
|
||||
# NOTE: syntax for function results: "func_name.RESULT"
|
||||
type_overrides = {
|
||||
overrides = {
|
||||
'sgl_error': 'sgl_get_error', # 'error' is reserved in Zig
|
||||
'sgl_deg': 'sgl_as_degrees',
|
||||
'sgl_rad': 'sgl_as_radians',
|
||||
'sg_context_desc.color_format': 'int',
|
||||
'sg_context_desc.depth_format': 'int',
|
||||
'sg_apply_uniforms.ub_index': 'uint32_t',
|
||||
@@ -53,6 +59,7 @@ type_overrides = {
|
||||
'sshape_element_range_t.base_element': 'uint32_t',
|
||||
'sshape_element_range_t.num_elements': 'uint32_t',
|
||||
'sdtx_font.font_index': 'uint32_t',
|
||||
'SGL_NO_ERROR': 'SGL_ERROR_NO_ERROR',
|
||||
}
|
||||
|
||||
prim_types = {
|
||||
@@ -92,6 +99,7 @@ prim_defaults = {
|
||||
'size_t': '0'
|
||||
}
|
||||
|
||||
|
||||
struct_types = []
|
||||
enum_types = []
|
||||
enum_items = {}
|
||||
@@ -107,9 +115,6 @@ def reset_globals():
|
||||
enum_items = {}
|
||||
out_lines = ''
|
||||
|
||||
re_1d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]$")
|
||||
re_2d_array = re.compile("^(?:const )?\w*\s\*?\[\d*\]\[\d*\]$")
|
||||
|
||||
def l(s):
|
||||
global out_lines
|
||||
out_lines += s + '\n'
|
||||
@@ -122,6 +127,7 @@ def as_zig_struct_type(s, prefix):
|
||||
parts = s.lower().split('_')
|
||||
outp = '' if s.startswith(prefix) else f'{parts[0]}.'
|
||||
for part in parts[1:]:
|
||||
# ignore '_t' type postfix
|
||||
if (part != 't'):
|
||||
outp += part.capitalize()
|
||||
return outp
|
||||
@@ -135,42 +141,20 @@ def as_zig_enum_type(s, prefix):
|
||||
outp += part.capitalize()
|
||||
return outp
|
||||
|
||||
def check_type_override(func_or_struct_name, field_or_arg_name, orig_type):
|
||||
s = f"{func_or_struct_name}.{field_or_arg_name}"
|
||||
if s in type_overrides:
|
||||
return type_overrides[s]
|
||||
else:
|
||||
return orig_type
|
||||
|
||||
def check_name_override(name):
|
||||
if name in name_overrides:
|
||||
return name_overrides[name]
|
||||
else:
|
||||
def check_override(name, default=None):
|
||||
if name in overrides:
|
||||
return overrides[name]
|
||||
elif default is None:
|
||||
return name
|
||||
else:
|
||||
return default
|
||||
|
||||
def check_name_ignore(name):
|
||||
return name in name_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):
|
||||
parts = s.lower().split('_')[1:]
|
||||
outp = parts[0]
|
||||
for part in parts[1:]:
|
||||
outp += part.capitalize()
|
||||
return outp
|
||||
def check_ignore(name):
|
||||
return name in ignores
|
||||
|
||||
# PREFIX_ENUM_BLA => Bla, _PREFIX_ENUM_BLA => Bla
|
||||
def as_enum_item_name(s):
|
||||
outp = s
|
||||
if outp.startswith('_'):
|
||||
outp = outp[1:]
|
||||
outp = s.lstrip('_')
|
||||
parts = outp.split('_')[2:]
|
||||
outp = '_'.join(parts)
|
||||
if outp[0].isdigit():
|
||||
@@ -189,15 +173,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} *":
|
||||
@@ -216,32 +191,10 @@ 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)
|
||||
|
||||
def is_2d_array_type(s):
|
||||
return re_2d_array.match(s)
|
||||
|
||||
def type_default_value(s):
|
||||
return prim_defaults[s]
|
||||
|
||||
def extract_array_type(s):
|
||||
return s[:s.index('[')].strip()
|
||||
|
||||
def extract_array_nums(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_extern_c_arg_type(arg_type, prefix):
|
||||
def as_c_arg_type(arg_type, prefix):
|
||||
if arg_type == "void":
|
||||
return "void"
|
||||
elif is_prim_type(arg_type):
|
||||
@@ -250,20 +203,20 @@ def as_extern_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):
|
||||
return "?*c_void"
|
||||
elif is_const_void_ptr(arg_type):
|
||||
return "?*const c_void"
|
||||
elif is_string_ptr(arg_type):
|
||||
elif util.is_void_ptr(arg_type):
|
||||
return "?*anyopaque"
|
||||
elif util.is_const_void_ptr(arg_type):
|
||||
return "?*const anyopaque"
|
||||
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:
|
||||
return '??? (as_extern_c_arg_type)'
|
||||
sys.exit(f"Error as_c_arg_type(): {arg_type}")
|
||||
|
||||
def as_zig_arg_type(arg_prefix, arg_type, prefix):
|
||||
# NOTE: if arg_prefix is None, the result is used as return value
|
||||
@@ -279,21 +232,24 @@ 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):
|
||||
return pre + "?*c_void"
|
||||
elif is_const_void_ptr(arg_type):
|
||||
return pre + "?*const c_void"
|
||||
elif is_string_ptr(arg_type):
|
||||
elif util.is_void_ptr(arg_type):
|
||||
return pre + "?*anyopaque"
|
||||
elif util.is_const_void_ptr(arg_type):
|
||||
return pre + "?*const anyopaque"
|
||||
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:
|
||||
return arg_prefix + "??? (as_zig_arg_type)"
|
||||
sys.exit(f"ERROR as_zig_arg_type(): {arg_type}")
|
||||
|
||||
def is_zig_string(zig_type):
|
||||
return zig_type == "[:0]const u8"
|
||||
|
||||
# get C-style arguments of a function pointer as string
|
||||
def funcptr_args_c(field_type, prefix):
|
||||
@@ -303,22 +259,24 @@ def funcptr_args_c(field_type, prefix):
|
||||
arg_type = token.strip()
|
||||
if s != "":
|
||||
s += ", "
|
||||
c_arg = as_extern_c_arg_type(arg_type, prefix)
|
||||
if (c_arg == "void"):
|
||||
c_arg = as_c_arg_type(arg_type, prefix)
|
||||
if c_arg == "void":
|
||||
return ""
|
||||
else:
|
||||
s += c_arg
|
||||
return s
|
||||
|
||||
# get C-style result of a function pointer as string
|
||||
def funcptr_res_c(field_type):
|
||||
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):
|
||||
return '?*const c_void'
|
||||
elif util.is_const_void_ptr(res_type):
|
||||
return '?*const anyopaque'
|
||||
elif util.is_void_ptr(res_type):
|
||||
return '?*anyopaque'
|
||||
else:
|
||||
return '???'
|
||||
sys.exit(f"ERROR funcptr_result_c(): {field_type}")
|
||||
|
||||
def funcdecl_args_c(decl, prefix):
|
||||
s = ""
|
||||
@@ -327,8 +285,8 @@ def funcdecl_args_c(decl, prefix):
|
||||
if s != "":
|
||||
s += ", "
|
||||
param_name = param_decl['name']
|
||||
param_type = check_type_override(func_name, param_name, param_decl['type'])
|
||||
s += as_extern_c_arg_type(param_type, prefix)
|
||||
param_type = check_override(f'{func_name}.{param_name}', default=param_decl['type'])
|
||||
s += as_c_arg_type(param_type, prefix)
|
||||
return s
|
||||
|
||||
def funcdecl_args_zig(decl, prefix):
|
||||
@@ -338,55 +296,49 @@ def funcdecl_args_zig(decl, prefix):
|
||||
if s != "":
|
||||
s += ", "
|
||||
param_name = param_decl['name']
|
||||
param_type = check_type_override(func_name, param_name, param_decl['type'])
|
||||
param_type = check_override(f'{func_name}.{param_name}', default=param_decl['type'])
|
||||
s += f"{as_zig_arg_type(f'{param_name}: ', param_type, prefix)}"
|
||||
return s
|
||||
|
||||
def funcdecl_result_c(decl, prefix):
|
||||
func_name = decl['name']
|
||||
decl_type = decl['type']
|
||||
result_type = check_type_override(func_name, 'RESULT', decl_type[:decl_type.index('(')].strip())
|
||||
return as_extern_c_arg_type(result_type, prefix)
|
||||
result_type = check_override(f'{func_name}.RESULT', default=decl_type[:decl_type.index('(')].strip())
|
||||
return as_c_arg_type(result_type, prefix)
|
||||
|
||||
def funcdecl_result_zig(decl, prefix):
|
||||
func_name = decl['name']
|
||||
decl_type = decl['type']
|
||||
result_type = check_type_override(func_name, 'RESULT', decl_type[:decl_type.index('(')].strip())
|
||||
result_type = check_override(f'{func_name}.RESULT', default=decl_type[:decl_type.index('(')].strip())
|
||||
zig_res_type = as_zig_arg_type(None, result_type, prefix)
|
||||
if zig_res_type == "":
|
||||
zig_res_type = "void"
|
||||
return zig_res_type
|
||||
|
||||
def gen_struct(decl, prefix, callconvc_funcptrs = True, use_raw_name=False, use_extern=True):
|
||||
struct_name = decl['name']
|
||||
zig_type = struct_name if use_raw_name else as_zig_struct_type(struct_name, prefix)
|
||||
l(f"pub const {zig_type} = {'extern ' if use_extern else ''}struct {{")
|
||||
def gen_struct(decl, prefix):
|
||||
struct_name = check_override(decl['name'])
|
||||
zig_type = as_zig_struct_type(struct_name, prefix)
|
||||
l(f"pub const {zig_type} = extern struct {{")
|
||||
for field in decl['fields']:
|
||||
field_name = field['name']
|
||||
field_type = field['type']
|
||||
field_type = check_type_override(struct_name, field_name, field_type)
|
||||
field_name = check_override(field['name'])
|
||||
field_type = check_override(f'{struct_name}.{field_name}', default=field['type'])
|
||||
if is_prim_type(field_type):
|
||||
l(f" {field_name}: {as_zig_prim_type(field_type)} = {type_default_value(field_type)},")
|
||||
elif is_struct_type(field_type):
|
||||
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):
|
||||
l(f" {field_name}: ?*const c_void = null,")
|
||||
elif is_void_ptr(field_type):
|
||||
l(f" {field_name}: ?*c_void = null,")
|
||||
elif util.is_const_void_ptr(field_type):
|
||||
l(f" {field_name}: ?*const anyopaque = null,")
|
||||
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):
|
||||
if callconvc_funcptrs:
|
||||
l(f" {field_name}: ?fn({funcptr_args_c(field_type, prefix)}) callconv(.C) {funcptr_res_c(field_type)} = null,")
|
||||
else:
|
||||
l(f" {field_name}: ?fn({funcptr_args_c(field_type, prefix)}) {funcptr_res_c(field_type)} = null,")
|
||||
elif is_1d_array_type(field_type):
|
||||
array_type = extract_array_type(field_type)
|
||||
array_nums = extract_array_nums(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}: ?*const fn({funcptr_args_c(field_type, prefix)}) callconv(.C) {funcptr_result_c(field_type)} = null,")
|
||||
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)
|
||||
@@ -398,19 +350,17 @@ def gen_struct(decl, prefix, callconvc_funcptrs = True, use_raw_name=False, use_
|
||||
zig_type = as_zig_enum_type(array_type, prefix)
|
||||
def_val = '.{}'
|
||||
else:
|
||||
zig_type = '??? (array type)'
|
||||
def_val = '???'
|
||||
t0 = f"[{array_nums[0]}]{zig_type}"
|
||||
t0_slice = f"[]const {zig_type}"
|
||||
sys.exit(f"ERROR gen_struct is_1d_array_type: {array_type}")
|
||||
t0 = f"[{array_sizes[0]}]{zig_type}"
|
||||
t1 = f"[_]{zig_type}"
|
||||
l(f" {field_name}: {t0} = {t1}{{{def_val}}} ** {array_nums[0]},")
|
||||
elif is_const_void_ptr(array_type):
|
||||
l(f" {field_name}: [{array_nums[0]}]?*const c_void = [_]?*const c_void {{ null }} ** {array_nums[0]},")
|
||||
l(f" {field_name}: {t0} = {t1}{{{def_val}}} ** {array_sizes[0]},")
|
||||
elif util.is_const_void_ptr(array_type):
|
||||
l(f" {field_name}: [{array_sizes[0]}]?*const anyopaque = [_]?*const anyopaque {{ null }} ** {array_sizes[0]},")
|
||||
else:
|
||||
l(f"// FIXME: ??? array {field_name}: {field_type} => {array_type} [{array_nums[0]}]")
|
||||
elif is_2d_array_type(field_type):
|
||||
array_type = extract_array_type(field_type)
|
||||
array_nums = extract_array_nums(field_type)
|
||||
sys.exit(f"ERROR gen_struct: array {field_name}: {field_type} => {array_type} [{array_sizes[0]}]")
|
||||
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)
|
||||
@@ -418,22 +368,23 @@ def gen_struct(decl, prefix, callconvc_funcptrs = True, use_raw_name=False, use_
|
||||
zig_type = as_zig_struct_type(array_type, prefix)
|
||||
def_val = ".{ }"
|
||||
else:
|
||||
zig_type = "???"
|
||||
def_val = "???"
|
||||
t0 = f"[{array_nums[0]}][{array_nums[1]}]{zig_type}"
|
||||
l(f" {field_name}: {t0} = [_][{array_nums[1]}]{zig_type}{{[_]{zig_type}{{ {def_val} }}**{array_nums[1]}}}**{array_nums[0]},")
|
||||
sys.exit(f"ERROR gen_struct is_2d_array_type: {array_type}")
|
||||
t0 = f"[{array_sizes[0]}][{array_sizes[1]}]{zig_type}"
|
||||
l(f" {field_name}: {t0} = [_][{array_sizes[1]}]{zig_type}{{[_]{zig_type}{{ {def_val} }}**{array_sizes[1]}}}**{array_sizes[0]},")
|
||||
else:
|
||||
l(f"// FIXME: {field_name}: {field_type};")
|
||||
sys.exit(f"ERROR gen_struct: {field_name}: {field_type};")
|
||||
l("};")
|
||||
|
||||
def gen_consts(decl, prefix):
|
||||
for item in decl['items']:
|
||||
l(f"pub const {as_snake_case(item['name'], prefix)} = {item['value']};")
|
||||
item_name = check_override(item['name'])
|
||||
l(f"pub const {util.as_lower_snake_case(item_name, prefix)} = {item['value']};")
|
||||
|
||||
def gen_enum(decl, prefix):
|
||||
l(f"pub const {as_zig_enum_type(decl['name'], prefix)} = enum(i32) {{")
|
||||
enum_name = check_override(decl['name'])
|
||||
l(f"pub const {as_zig_enum_type(enum_name, prefix)} = enum(i32) {{")
|
||||
for item in decl['items']:
|
||||
item_name = as_enum_item_name(item['name'])
|
||||
item_name = as_enum_item_name(check_override(item['name']))
|
||||
if item_name != "FORCE_U32":
|
||||
if 'value' in item:
|
||||
l(f" {item_name} = {item['value']},")
|
||||
@@ -446,27 +397,36 @@ def gen_func_c(decl, prefix):
|
||||
|
||||
def gen_func_zig(decl, prefix):
|
||||
c_func_name = decl['name']
|
||||
zig_func_name = as_camel_case(check_name_override(decl['name']))
|
||||
zig_res_type = funcdecl_result_zig(decl, prefix)
|
||||
l(f"pub fn {zig_func_name}({funcdecl_args_zig(decl, prefix)}) {zig_res_type} {{")
|
||||
if zig_res_type != 'void':
|
||||
s = f" return {c_func_name}("
|
||||
zig_func_name = util.as_lower_camel_case(check_override(decl['name']), prefix)
|
||||
if c_func_name in c_callbacks:
|
||||
# a simple forwarded C callback function
|
||||
l(f"pub const {zig_func_name} = {c_func_name};")
|
||||
else:
|
||||
s = f" {c_func_name}("
|
||||
for i, param_decl in enumerate(decl['params']):
|
||||
if i > 0:
|
||||
s += ", "
|
||||
arg_name = param_decl['name']
|
||||
arg_type = param_decl['type']
|
||||
if is_const_struct_ptr(arg_type):
|
||||
s += f"&{arg_name}"
|
||||
elif is_string_ptr(arg_type):
|
||||
s += f"@ptrCast([*c]const u8,{arg_name})"
|
||||
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):
|
||||
# special case: convert C string to Zig string slice
|
||||
s = f" return cStrToZig({c_func_name}("
|
||||
elif zig_res_type != 'void':
|
||||
s = f" return {c_func_name}("
|
||||
else:
|
||||
s += arg_name
|
||||
s += ");"
|
||||
l(s)
|
||||
l("}")
|
||||
s = f" {c_func_name}("
|
||||
for i, param_decl in enumerate(decl['params']):
|
||||
if i > 0:
|
||||
s += ", "
|
||||
arg_name = param_decl['name']
|
||||
arg_type = param_decl['type']
|
||||
if is_const_struct_ptr(arg_type):
|
||||
s += f"&{arg_name}"
|
||||
elif util.is_string_ptr(arg_type):
|
||||
s += f"@ptrCast([*c]const u8,{arg_name})"
|
||||
else:
|
||||
s += arg_name
|
||||
if is_zig_string(zig_res_type):
|
||||
s += ")"
|
||||
s += ");"
|
||||
l(s)
|
||||
l("}")
|
||||
|
||||
def pre_parse(inp):
|
||||
global struct_types
|
||||
@@ -483,12 +443,17 @@ def pre_parse(inp):
|
||||
enum_items[enum_name].append(as_enum_item_name(item['name']))
|
||||
|
||||
def gen_imports(inp, dep_prefixes):
|
||||
l('const builtin = @import("builtin");')
|
||||
for dep_prefix in dep_prefixes:
|
||||
dep_module_name = module_names[dep_prefix]
|
||||
l(f'const {dep_prefix[:-1]} = @import("{dep_module_name}.zig");')
|
||||
l('')
|
||||
l('')
|
||||
|
||||
def gen_helpers(inp):
|
||||
l('// helper function to convert a C string to a Zig string slice')
|
||||
l('fn cStrToZig(c_str: [*c]const u8) [:0]const u8 {')
|
||||
l(' return @import("std").mem.span(c_str);')
|
||||
l('}')
|
||||
if inp['prefix'] in ['sg_', 'sdtx_', 'sshape_']:
|
||||
l('// helper function to convert "anything" to a Range struct')
|
||||
l('pub fn asRange(val: anytype) Range {')
|
||||
@@ -502,7 +467,7 @@ def gen_helpers(inp):
|
||||
l(' }')
|
||||
l(' },')
|
||||
l(' .Struct, .Array => {')
|
||||
l(' return .{ .ptr = &val, .size = @sizeOf(@TypeOf(val)) };')
|
||||
l(' @compileError("Structs and arrays must be passed as pointers to asRange");')
|
||||
l(' },')
|
||||
l(' else => {')
|
||||
l(' @compileError("Cannot convert to range!");')
|
||||
@@ -547,7 +512,7 @@ def gen_module(inp, dep_prefixes):
|
||||
kind = decl['kind']
|
||||
if kind == 'consts':
|
||||
gen_consts(decl, prefix)
|
||||
elif not check_name_ignore(decl['name']):
|
||||
elif not check_ignore(decl['name']):
|
||||
if kind == 'struct':
|
||||
gen_struct(decl, prefix)
|
||||
elif kind == 'enum':
|
||||
@@ -557,13 +522,16 @@ def gen_module(inp, dep_prefixes):
|
||||
gen_func_zig(decl, prefix)
|
||||
|
||||
def prepare():
|
||||
print('Generating zig bindings:')
|
||||
print('=== Generating Zig bindings:')
|
||||
if not os.path.isdir('sokol-zig/src/sokol'):
|
||||
os.makedirs('sokol-zig/src/sokol')
|
||||
if not os.path.isdir('sokol-zig/src/sokol/c'):
|
||||
os.makedirs('sokol-zig/src/sokol/c')
|
||||
|
||||
def gen(c_header_path, c_prefix, dep_c_prefixes):
|
||||
if not c_prefix in module_names:
|
||||
print(f' >> warning: skipping generation for {c_prefix} prefix...')
|
||||
return
|
||||
module_name = module_names[c_prefix]
|
||||
c_source_path = c_source_paths[c_prefix]
|
||||
print(f' {c_header_path} => {module_name}')
|
||||
|
||||
Reference in New Issue
Block a user