mirror of
https://github.com/DrBeef/JKXR.git
synced 2024-11-25 21:41:11 +00:00
167 lines
4.4 KiB
Python
167 lines
4.4 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
import argparse
|
||
|
import jinja2
|
||
|
import re
|
||
|
from yaml import load
|
||
|
|
||
|
split_re = re.compile(r'^(?P<type>.*?)\s*(?P<name>\w+)$')
|
||
|
env = jinja2.Environment(
|
||
|
trim_blocks=True,
|
||
|
lstrip_blocks=True,
|
||
|
loader=jinja2.FileSystemLoader('template'),
|
||
|
)
|
||
|
|
||
|
def args(args, add_type=True):
|
||
|
return ', '.join(
|
||
|
'{} {}'.format(arg['type'], arg['name']) if add_type else arg['name']
|
||
|
for arg in args
|
||
|
)
|
||
|
|
||
|
f = '0.2f'
|
||
|
printf_lookup = {
|
||
|
'GLbitfield': 'd',
|
||
|
'GLboolean': 'd',
|
||
|
'GLbyte': 'c',
|
||
|
'GLubyte': 'c',
|
||
|
'GLchar': 'c',
|
||
|
'GLdouble': '0.2f',
|
||
|
'GLenum': 'u',
|
||
|
'GLfloat': '0.2f',
|
||
|
'GLint': 'd',
|
||
|
'GLintptr': 'd',
|
||
|
'GLintptrARB': 'd',
|
||
|
'GLshort': 'd',
|
||
|
'GLsizei': 'd',
|
||
|
'GLsizeiptr': 'd',
|
||
|
'GLsizeiptrARB': 'd',
|
||
|
'GLuint': 'u',
|
||
|
'GLushort': 'u',
|
||
|
'GLvoid': 'p',
|
||
|
}
|
||
|
|
||
|
def printf(args):
|
||
|
types = []
|
||
|
for arg in args:
|
||
|
typ = arg['type']
|
||
|
if '*' in typ:
|
||
|
t = 'p'
|
||
|
else:
|
||
|
t = printf_lookup.get(typ, 'p')
|
||
|
|
||
|
types.append(t)
|
||
|
|
||
|
return ', '.join('%' + t for t in types)
|
||
|
|
||
|
def unconst(s):
|
||
|
split = s.split(' ')
|
||
|
while 'const' in split:
|
||
|
split.remove('const')
|
||
|
return ' '.join(split)
|
||
|
|
||
|
env.filters['args'] = args
|
||
|
env.filters['printf'] = printf
|
||
|
env.filters['unconst'] = unconst
|
||
|
|
||
|
def split_arg(arg):
|
||
|
match = split_re.match(arg)
|
||
|
if match:
|
||
|
return match.groupdict()
|
||
|
else:
|
||
|
return {'type': 'unknown', 'name': arg}
|
||
|
|
||
|
def gen(files, template, guard_name, headers,
|
||
|
deep=False, cats=(), ifdef=None, ifndef=None):
|
||
|
funcs = {}
|
||
|
formats = []
|
||
|
unique_formats = set()
|
||
|
for data in files:
|
||
|
if deep and not isinstance(data.values()[0], list):
|
||
|
functions = []
|
||
|
for cat, f in data.items():
|
||
|
if not cats or cat in cats:
|
||
|
functions.extend(f.items())
|
||
|
else:
|
||
|
functions = data.items()
|
||
|
|
||
|
for name, args in sorted(functions):
|
||
|
props = {}
|
||
|
if args:
|
||
|
ret = args.pop(0)
|
||
|
else:
|
||
|
ret = 'void'
|
||
|
|
||
|
loadlib = 'LOAD_GLES'
|
||
|
if name.endswith('_OES_'):
|
||
|
loadlib = 'LOAD_GLES_OES'
|
||
|
name = name[:-5]
|
||
|
|
||
|
args = [split_arg(arg) for arg in args if not arg == 'void']
|
||
|
if any(arg.get('type') == 'unknown' for arg in args):
|
||
|
continue
|
||
|
|
||
|
if args:
|
||
|
args[0]['first'] = True
|
||
|
args[-1]['last'] = True
|
||
|
|
||
|
for i, arg in enumerate(args):
|
||
|
arg['index'] = i
|
||
|
|
||
|
types = '_'.join(
|
||
|
arg['type'].replace(' ', '_').replace('*', '__GENPT__')
|
||
|
for arg in [{'type': ret}] + args)
|
||
|
|
||
|
props.update({
|
||
|
'return': ret,
|
||
|
'name': name,
|
||
|
'args': args,
|
||
|
'types': types,
|
||
|
'void': ret == 'void',
|
||
|
'loadlib': loadlib,
|
||
|
})
|
||
|
if not types in unique_formats:
|
||
|
unique_formats.add(types)
|
||
|
formats.append(props)
|
||
|
|
||
|
funcs[name] = props
|
||
|
|
||
|
context = {
|
||
|
'functions': [i[1] for i in sorted(funcs.items())],
|
||
|
'formats': formats,
|
||
|
'headers': headers,
|
||
|
'name': guard_name,
|
||
|
'ifdef': ifdef,
|
||
|
'ifndef': ifndef,
|
||
|
}
|
||
|
|
||
|
t = env.get_template(template)
|
||
|
return t.render(**context).rstrip('\n')
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
parser = argparse.ArgumentParser(description='Generate code with yml/jinja.')
|
||
|
parser.add_argument('yaml', help='spec files')
|
||
|
parser.add_argument('template', help='jinja template to load')
|
||
|
parser.add_argument('name', help='header guard name')
|
||
|
parser.add_argument('headers', nargs='*', help='headers to include')
|
||
|
parser.add_argument('--deep', help='nested definitions', action='store_true')
|
||
|
parser.add_argument('--cats', help='deep category filter')
|
||
|
parser.add_argument('--ifdef', help='wrap with ifdef')
|
||
|
parser.add_argument('--ifndef', help='wrap with ifndef')
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
files = []
|
||
|
for name in args.yaml.split(','):
|
||
|
with open(name) as f:
|
||
|
data = load(f)
|
||
|
if data:
|
||
|
files.append(data)
|
||
|
|
||
|
if args.cats:
|
||
|
cats = args.cats.split(',')
|
||
|
else:
|
||
|
cats = None
|
||
|
print gen(files, args.template, args.name,
|
||
|
args.headers, args.deep, cats,
|
||
|
args.ifdef, args.ifndef)
|