#! /usr/bin/python

# procdl.py
#
# FRT - A Godot platform targeting single board computers
# Copyright (c) 2017-2022  Emanuele Fornara
# SPDX-License-Identifier: MIT
#

import re

def parse_dl(dl, suffix):
	libname = 'unnamed'
	head = ''
	symbols = []
	types = []
	includes = []
	f_dl = open(dl, 'r')
	for line in f_dl.readlines():
		line = line.replace('\n', '')
		if libname == 'unnamed':
			m = re.search(r'^//\s*(.*)\.dl\s*$', line)
			if m:
				libname = m.group(1)
				head += '// ' + libname + suffix
				head += ' - File generated by procdl.py - DO NOT EDIT\n'
				continue
		m = re.search(r'^.*___(.*)___.*$', line)
		if not m:
			if re.search(r'^#include', line):
				includes.append(line)
			else:
				head += line + '\n'
			continue
		s = m.group(1)
		symbols.append(s)
		ls = libname + '_' + s
		types.append(line.replace('___' + s + '___', 'FRT_FN_' + ls))
	f_dl.close()
	return (libname, head, symbols, types, includes)

def build_h(dl, h):
	libname, head, symbols, types, includes = parse_dl(dl, '.gen.h')
	f = open(h, 'w')
	f.write(head)
	def out(s=None):
		if s:
			f.write(s)
		f.write('\n')
	out('#ifndef FRT_DL_SKIP')
	for s in includes:
		out(s)
	out()
	for s in types:
		out(s)
	out()
	for s in symbols:
		ls = libname + '_' + s
		out('#define ' + s + ' frt_fn_' + ls)
	out()
	for s in symbols:
		ls = libname + '_' + s
		out('extern FRT_FN_' + ls + ' frt_fn_' + ls + ';')
	out()
	out('#endif')
	out('typedef void *(*FRT_FN_' + libname + '_GetProcAddress)(const char *name);')
	out('extern void frt_resolve_symbols_' + libname + '(FRT_FN_' + libname + '_GetProcAddress get_proc_address);')
	f.close()

def build_cc(dl, cc):
	libname, head, symbols, types, includes = parse_dl(dl, '.gen.cc')
	f = open(cc, 'w')
	f.write(head)
	assignments = ''
	for s in symbols:
		ls = libname + '_' + s
		assignments += 'FRT_FN_' + ls + ' frt_fn_' + ls + ' = 0;\n'
	resolutions = ''
	for s in symbols:
		ls = libname + '_' + s
		resolutions += '\tfrt_fn_' + ls + ' = (FRT_FN_' + ls + ')'
		resolutions += 'get_proc_address("' + s + '");\n'
	f.write("""\
#include "%(libname)s.gen.h"

#include <stdio.h>

%(assignments)s

void frt_resolve_symbols_%(libname)s(FRT_FN_%(libname)s_GetProcAddress get_proc_address) {
%(resolutions)s
}
""" % {
		'libname': libname,
		'assignments': assignments[:-1],
		'resolutions': resolutions[:-1]
	})
	f.close()

def build_cc_action(target, source, env):
	build_cc(str(source[0]), str(target[0]))

def build_h_action(target, source, env):
	build_h(str(source[0]), str(target[0]))

if __name__ == '__main__':
	import sys
	for s in sys.argv[1:]:
		sys.stdout.write('Processing ' + s + '... ')
		build_cc(s, s.replace('.dl', '.gen.cc'))
		build_h(s, s.replace('.dl', '.gen.h'))
		sys.stdout.write('done.\n')
