aboutsummaryrefslogtreecommitdiffstats
path: root/extra-tools
diff options
context:
space:
mode:
Diffstat (limited to 'extra-tools')
-rwxr-xr-xextra-tools/luatablegen.py289
-rw-r--r--extra-tools/tablegen-test/post.txt1
-rw-r--r--extra-tools/tablegen-test/pre.txt2
-rwxr-xr-xextra-tools/tablegen-test/run.sh4
4 files changed, 296 insertions, 0 deletions
diff --git a/extra-tools/luatablegen.py b/extra-tools/luatablegen.py
new file mode 100755
index 0000000..a4569ca
--- /dev/null
+++ b/extra-tools/luatablegen.py
@@ -0,0 +1,289 @@
+#!/usr/bin/python3
+
+import argparse
+import code
+import json
+import os
+import readline
+import signal
+import sys
+
+C_STRUCT = ['typedef struct XXX {', '}XXX;']
+HEADER_GUARD = ['\n#ifndef _XXX_H\n#define _XXX_H\n', '#endif //end of inclusion guard\n\n']
+EXTERN_C = ['#ifdef __cplusplus\nextern "C" {\n#endif\n', '#ifdef __cplusplus\n}\n#endif //end of extern c\n']
+BEGIN_NOTE = "//Generated Automatically by luatablegen."
+HEADER_LIST = ['#include "HHHlua.h"\n', '#include "HHHlauxlib.h"\n',
+ '#include "HHHlualib.h"\n', '#include <inttypes.h>\n',
+ '#include <stdbool.h>']
+CONVERT = ['static XXX* convert_XXX (lua_State* __ls, int index) {\n',
+ '\tXXX* dummy = (XXX*)lua_touserdata(__ls, index);\n',
+ '\tif (dummy == NULL) printf("XXX:bad user data type.\\n");\n',
+ '\treturn dummy;\n}\n']
+CHECK = ['static XXX* check_XXX(lua_State* __ls, int index) {\n',
+ '\tXXX* dummy;\n',
+ '\tluaL_checktype(__ls, index, LUA_TUSERDATA);\n'
+ '\tdummy = (XXX*)luaL_checkudata(__ls, index, "XXX");\n',
+ '\tif (dummy == NULL) printf("XXX:bad user data type.\\n");\n',
+ '\treturn dummy;\n}\n']
+PUSH_SELF = [ 'XXX* push_XXX(lua_State* __ls) {\n',
+ '\tlua_checkstack(__ls, 1);\n',
+ '\tXXX* dummy = lua_newuserdata(__ls, sizeof(XXX));\n',
+ '\tluaL_getmetatable(__ls, "XXX");\n',
+ '\tlua_setmetatable(__ls, -2);\n',
+ '\treturn dummy;\n}\n']
+PUSH_ARGS = ['int XXX_push_args(lua_State* __ls, XXX* _st) {\n',
+ '\tlua_checkstack(__ls, NNN);\n', '\treturn 0;\n}\n']
+NEW = ['int new_XXX(lua_State* __ls) {\n', '\tlua_checkstack(__ls, NNN);\n',
+ '\tXXX* dummy = push_XXX(__ls);\n', '\treturn 1;\n}\n']
+GETTER_GEN = ['static int getter_XXX_YYY(lua_State* __ls) {\n',
+ '\tXXX* dummy = check_XXX(__ls, 1);\n',
+ '\tlua_pop(__ls, -1);\n',
+ '\treturn 1;\n}\n']
+SETTER_GEN = ['static int setter_XXX_YYY(lua_State* __ls) {\n',
+ '\tXXX* dummy = check_XXX(__ls, 1);\n',
+ '\tlua_settop(__ls, 1);\n',
+ '\treturn 1;\n}\n']
+REGISTER_TABLE_METHODS = ['static const luaL_Reg XXX_methods[] = {\n',
+ '\t{0,0}\n};\n']
+REGISTER_META = ['static const luaL_Reg XXX_meta[] = {\n',
+ '\t{0, 0}\n};\n']
+TABLE_REGISTER = ['int XXX_register(lua_State* __ls) {\n',
+ '\tluaL_openlib(__ls, "XXX", XXX_methods, 0);\n',
+ '\tluaL_newmetatable(__ls, "XXX");\n',
+ '\tluaL_openlib(__ls, 0, XXX_meta, 0);\n',
+ '\tlua_pushliteral(__ls, "__index");\n',
+ '\tlua_pushvalue(__ls, -3);\n',
+ '\tlua_rawset(__ls, -3);\n',
+ '\tlua_pushliteral(__ls, "__metatable");\n',
+ '\tlua_pushvalue(__ls, -3);\n',
+ '\tlua_rawset(__ls, -3);\n',
+ '\tlua_pop(__ls, 1);\n',
+ 'return 1;\n}\n']
+SOURCE_FILE_NAME='XXX_luatablegen.c'
+HEADER_FILE_NAME='XXX_luatablegen.h'
+
+def SigHandler_SIGINT(signum, frame):
+ print()
+ sys.exit(0)
+
+class Argparser(object):
+ def __init__(self):
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--out", type=str, help="output directory")
+ parser.add_argument("--tbg", type=str, help="the table gen file")
+ parser.add_argument("--pre", type=str, help="path to source code file to add after header guard/extern c")
+ parser.add_argument("--post", type=str, help="path to source code file to add before header guard/extern c end")
+ parser.add_argument("--luaheader", type=str, help="path to lua header files")
+ parser.add_argument("--dbg", action="store_true", help="debug", default=False)
+ self.args = parser.parse_args()
+
+class TbgParser(object):
+ def __init__(self, tbg, out, argparser):
+ self.tbg_file = json.load(open(tbg))
+ self.argparser = argparser
+
+ def begin(self, c_source, h_filename, struct_name):
+ for header in HEADER_LIST:
+ if self.argparser.args.luaheader:
+ c_source.write(header.replace("HHH", self.argparser.args.luaheader+"/"))
+ else:
+ c_source.write(header.replace("HHH", ""))
+ c_source.write(HEADER_GUARD[0].replace("XXX", struct_name))
+ c_source.write(EXTERN_C[0])
+ #c_source.write('#include "./'+h_filename+'"\n')
+ c_source.write("\n")
+ if self.argparser.args.pre:
+ pre_file = open(self.argparser.args.pre)
+ for line in pre_file:
+ c_source.write(line)
+ c_source.write("\n")
+ pre_file.close()
+
+ def struct(self, c_source, field_names, field_types, struct_name):
+ c_source.write("typedef struct {\n")
+ for field_type, field_name in zip(field_types, field_names):
+ c_source.write("\t" + field_type + " " + field_name + ";\n")
+ c_source.write("}" +struct_name+ ";\n")
+ c_source.write("\n")
+
+ def convert(self, c_source, struct_name):
+ for line in CONVERT:
+ c_source.write(line.replace("XXX", struct_name))
+ c_source.write("\n")
+
+ def check(self, c_source, struct_name):
+ for line in CHECK:
+ c_source.write(line.replace("XXX", struct_name))
+ c_source.write("\n")
+
+ def push_self(self, c_source, struct_name):
+ for line in PUSH_SELF:
+ c_source.write(line.replace("XXX", struct_name))
+ c_source.write("\n")
+
+ def push_args(self, c_source, struct_name, field_names, lua_types):
+ dummy = str()
+ c_source.write(PUSH_ARGS[0].replace("XXX", struct_name))
+ c_source.write("\tlua_checkstack(__ls, " + repr(len(field_names)) + ");\n")
+ for field_name, lua_type in zip(field_names, lua_types):
+ if lua_type == "integer": dummy = "\tlua_pushinteger(__ls, _st->"+field_name+");\n"
+ elif lua_type == "lightuserdata": dummy = "\tlua_pushlightuserdata(__ls, _st->"+field_name+");\n"
+ elif lua_type == "number": dummy = "\tlua_pushnumber(__ls, _st->"+field_name+");\n"
+ elif lua_type == "string": dummy = "\tlua_pushstring(__ls, _st->"+field_name+");\n"
+ elif lua_type == "boolean": dummy = "\tlua_pushboolean(__ls, _st->"+field_name+");\n"
+ else:
+ print("bad lua_type entry in the json file")
+ sys.exit(1)
+ c_source.write(dummy)
+ dummy = str()
+ c_source.write(PUSH_ARGS[2])
+ c_source.write("\n")
+
+ def new(self, c_source, struct_name, field_types, field_names, lua_types):
+ dummy = str()
+ rev_counter = -len(field_types)
+ c_source.write(NEW[0].replace("XXX", struct_name))
+ c_source.write("\tlua_checkstack(__ls, " + repr(len(field_names)) + ");\n")
+ for lua_type, field_name, field_type in zip(lua_types, field_names, field_types):
+ if lua_type == "integer": dummy = "\t"+field_type +" "+field_name+" = "+"luaL_optinteger(__ls,"+repr(rev_counter)+",0);\n"
+ elif lua_type == "lightuserdata": dummy = "\t"+field_type +" "+field_name+" = "+"lua_touserdata(__ls,"+repr(rev_counter)+");\n"
+ elif lua_type == "number": pass
+ elif lua_type == "string":dummy = "\t"+field_type +" "+field_name+" = "+"lua_tostring(__ls,"+repr(rev_counter)+",0);\n"
+ elif lua_type == "boolean": pass
+ else:
+ print("bad lua_type entry in the json file")
+ sys.exit(1)
+ rev_counter += 1
+ c_source.write(dummy)
+ dummy = str()
+ c_source.write(NEW[2].replace("XXX", struct_name))
+ for field_name in field_names:
+ c_source.write("\tdummy->" + field_name + " = " + field_name + ";\n")
+ c_source.write(NEW[3].replace("XXX", struct_name))
+ c_source.write("\n")
+
+ def getter(self, c_source, struct_name, field_names, field_types, lua_types):
+ dummy = str()
+ for field_name, lua_type in zip(field_names, lua_types):
+ c_source.write(GETTER_GEN[0].replace("XXX", struct_name).replace("YYY", field_name))
+ c_source.write(GETTER_GEN[1].replace("XXX", struct_name))
+ c_source.write(GETTER_GEN[2])
+ if lua_type == "integer": dummy = "\tlua_pushinteger(__ls, dummy->"+field_name+");\n"
+ elif lua_type == "lightuserdata": dummy = "\tlua_pushlightuserdata(__ls, dummy->"+field_name+");\n"
+ elif lua_type == "number": dummy = "\tlua_pushnumber(__ls, dummy->"+field_name+");\n"
+ elif lua_type == "string": dummy = "\tlua_pushstring(__ls, dummy->"+field_name+");\n"
+ elif lua_type == "boolean": dummy = "\tlua_pushboolean(__ls, dummy->"+field_name+");\n"
+ else:
+ print("bad lua_type entry in the json file")
+ sys.exit(1)
+ c_source.write(dummy)
+ dummy = str()
+ c_source.write(GETTER_GEN[3])
+ c_source.write("\n")
+
+ def setter(self, c_source, struct_name, field_names, field_types, lua_types):
+ dummy = str()
+ for field_name, lua_type in zip(field_names, lua_types):
+ c_source.write(SETTER_GEN[0].replace("XXX", struct_name).replace("YYY", field_name))
+ c_source.write(SETTER_GEN[1].replace("XXX", struct_name))
+ if lua_type == "integer": dummy = "\tdummy->" + field_name + " = " + "luaL_checkinteger(__ls, 2);\n"
+ elif lua_type == "lightuserdata": dummy ="\tdummy->" + field_name + " = " + "luaL_checkudata(__ls, 2, "+'"'+struct_name+'"'+");\n"
+ elif lua_type == "number": dummy ="\tdummy->" + field_name + " = " + "luaL_checknumber(__ls, 2);\n"
+ elif lua_type == "string": dummy ="\tdummy->" + field_name + " = " + "luaL_checkstring(__ls, 2);\n"
+ elif lua_type == "boolean": pass
+ else:
+ print("bad lua_type entry in the json file")
+ sys.exit(1)
+ c_source.write(dummy)
+ dummy = str()
+ c_source.write(SETTER_GEN[2])
+ c_source.write(SETTER_GEN[3])
+ c_source.write("\n")
+
+ def gc(self):
+ pass
+ def tostring(self):
+ pass
+
+ def register_table_methods(self, c_source, struct_name, field_names):
+ c_source.write(REGISTER_TABLE_METHODS[0].replace("XXX", struct_name))
+ c_source.write('\t{"new", ' + "new_" + struct_name + "},\n")
+ for field_name in field_names:
+ c_source.write("\t{" + '"set_' + field_name + '"' + ", " + "setter_"+struct_name +"_"+ field_name + "},\n")
+ for field_name in field_names:
+ c_source.write("\t{" + '"' + field_name + '", ' + "getter_"+struct_name+"_"+field_name+"},\n")
+ c_source.write(REGISTER_TABLE_METHODS[1])
+ c_source.write("\n")
+
+ def register_table_meta(self, c_source, struct_name):
+ c_source.write(REGISTER_META[0].replace("XXX", struct_name))
+ c_source.write(REGISTER_META[1])
+ c_source.write("\n")
+
+ def register_table(self, c_source, struct_name):
+ for line in TABLE_REGISTER:
+ c_source.write(line.replace("XXX", struct_name))
+
+ def end(self, c_source):
+ if self.argparser.args.post:
+ c_source.write("\n")
+ post_file = open(self.argparser.args.post)
+ for line in post_file:
+ c_source.write(line)
+ c_source.write("\n")
+ c_source.write(EXTERN_C[1])
+ c_source.write(HEADER_GUARD[1])
+ c_source.write("\n")
+
+ def run(self):
+ for k, v in self.tbg_file.items():
+ struct_name = k
+ field_names = v['field_name']
+ field_types = v['field_type']
+ lua_types = v['lua_type']
+ methods = v['methods']
+ c_filename = struct_name + "_tablegen.h"
+ h_filename = struct_name + "_tablegen.h"
+ if self.argparser.args.out[-1] == "/":
+ c_source = open(self.argparser.args.out + c_filename, "w")
+ else:
+ c_source = open(self.argparser.args.out + "/" + c_filename, "w")
+ self.begin(c_source, h_filename, struct_name)
+ self.struct(c_source, field_names, field_types, struct_name)
+ self.convert(c_source, struct_name)
+ self.check(c_source, struct_name)
+ self.push_self(c_source, struct_name)
+ self.push_args(c_source, struct_name, field_names, lua_types)
+ self.new(c_source, struct_name, field_types, field_names, lua_types)
+ self.getter(c_source, struct_name, field_names, field_types, lua_types)
+ self.setter(c_source, struct_name, field_names, field_types, lua_types)
+ self.register_table_methods(c_source, struct_name, field_names)
+ self.register_table_meta(c_source, struct_name)
+ self.register_table(c_source, struct_name)
+ self.end(c_source)
+ c_source.close()
+
+# write code here
+def premain(argparser):
+ signal.signal(signal.SIGINT, SigHandler_SIGINT)
+ #here
+ parser = TbgParser(argparser.args.tbg, argparser.args.out, argparser)
+ parser.run()
+
+def main():
+ argparser = Argparser()
+ if argparser.args.dbg:
+ try:
+ premain(argparser)
+ except Exception as e:
+ print(e.__doc__)
+ if e.message: print(e.message)
+ variables = globals().copy()
+ variables.update(locals())
+ shell = code.InteractiveConsole(variables)
+ shell.interact(banner="DEBUG REPL")
+ else:
+ premain(argparser)
+
+if __name__ == "__main__":
+ main()
diff --git a/extra-tools/tablegen-test/post.txt b/extra-tools/tablegen-test/post.txt
new file mode 100644
index 0000000..e27cdda
--- /dev/null
+++ b/extra-tools/tablegen-test/post.txt
@@ -0,0 +1 @@
+// bye bye
diff --git a/extra-tools/tablegen-test/pre.txt b/extra-tools/tablegen-test/pre.txt
new file mode 100644
index 0000000..0819fdc
--- /dev/null
+++ b/extra-tools/tablegen-test/pre.txt
@@ -0,0 +1,2 @@
+enum jmp_type {NONE=0, JMP=1, JNE=2, JE=3};
+#define JMP_T enum jmp_type
diff --git a/extra-tools/tablegen-test/run.sh b/extra-tools/tablegen-test/run.sh
new file mode 100755
index 0000000..f9eda4d
--- /dev/null
+++ b/extra-tools/tablegen-test/run.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/bash
+cd $(dirname $0)
+../luatablegen.py --tbg ../wasmtablegen.json --out ./ --luaheader ../../bruiser/lua-5.3.4/src --pre ./pre.txt --post ./post.txt
+less ./jmp_s_t_tablegen.h