add support for export and import symbols

adds a lot of improvement to the script
- proper CLI
- generate a api_require.h which contains a function that export the symbols
This commit is contained in:
takase1121 2021-11-06 19:22:55 +08:00
parent 46f9bcb90c
commit a9d7ddc6e1
No known key found for this signature in database
GPG Key ID: 60EEFFC68EB3031B
1 changed files with 124 additions and 35 deletions

View File

@ -23,16 +23,19 @@ discard_preprocessors() {
# sed regex for extracting data from function signature
# if this isn't regex, idk what is
# LUA_API (return type as \2) (function name as \3) (args as \4)
sym_regex='^LUA\(LIB\)\?_API\s\+\([^(]\+\)\s*(\([^)]\+\))\s\+(\([^)]\+\))'
sym_regex='^LUA\(LIB\)\?_API\s\+\([^(]\+\)\s*(\([^)]\+\))\s\+(\([^)]\+\));'
# get funcptr declarations
ptrize() {
grep '^LUA' | sed -e "s/$sym_regex/static \2(*\3) (\4)/"
grep '^LUA' | sed -e "s/$sym_regex/static \2(*\3) (\4);/"
}
import_sym() {
grep '^LUA' | sed -e "s/$sym_regex/\tIMPORT_SYMBOL(\3, \2, \4);/"
}
export_sym() {
# don't even bother reading this again
grep '^LUA' | sed -e "s/$sym_regex/\tIMPORT_SYMBOL(\3, \2, \4)/"
grep '^LUA' | sed -e "s/$sym_regex/\t\tEXPORT_SYMBOL(\3),/"
}
decl() {
@ -47,48 +50,134 @@ decl() {
grep '^#' <<< "$header"
}
decl_import() {
uncomment $1 | onelineize | import_sym
}
decl_export() {
uncomment $1 | onelineize | export_sym
}
LUA_PATH="$1"
cat << EOF
/**
The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long
as it has an entrypoint that looks like the following, where xxxxx is the plugin name:
#include "lite_xl_plugin_api.h"
int lua_open_lite_xl_xxxxx(lua_State* L, void* XL) {
lite_xl_plugin_init(XL);
...
return 1;
generate_header() {
local LUA_PATH="$1"
echo "#ifndef LITE_XL_PLUGIN_API"
echo "#define LITE_XL_PLUGIN_API"
echo "/**"
echo "The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long"
echo "as it has an entrypoint that looks like the following, where xxxxx is the plugin name:"
echo '#include "lite_xl_plugin_api.h"'
echo "int lua_open_lite_xl_xxxxx(lua_State* L, void* XL) {"
echo " lite_xl_plugin_init(XL);"
echo " ..."
echo " return 1;"
echo "}"
echo "In linux, to compile this file, you'd do: 'gcc -o xxxxx.so -shared xxxxx.c'. Simple!"
echo "Due to the way the API is structured, you *should not* link or include lua libraries."
echo "This file was automatically generated by the below code. DO NOT MODIFY DIRECTLY."
echo
echo
cat "$0"
echo "**/"
echo "#include <stddef.h>"
decl "$LUA_PATH/lua.h"
decl "$LUA_PATH/lauxlib.h"
echo "#define IMPORT_SYMBOL(name, ret, ...) name = (ret (*) (__VA_ARGS__)) symbol(#name)"
echo "static void lite_xl_plugin_init(void *XL) {"
echo -e "\tvoid* (*symbol)(const char *) = (void* (*) (const char *)) XL;"
decl_import "$LUA_PATH/lua.h"
decl_import "$LUA_PATH/lauxlib.h"
echo "}"
echo "#endif"
}
In linux, to compile this file, you'd do: 'gcc -o xxxxx.so -shared xxxxx.c'. Simple!
Due to the way the API is structured, you *should not* link or include lua libraries.
This file was automatically generated by the below code. Do NOT MODIFY DIRECTLY.
generate_api_require() {
local LUA_PATH="$1"
echo "#ifndef API_REQUIRE_H"
echo "#define API_REQUIRE_H"
echo "/**"
echo "This file contains the function api_require that"
echo "returns a function pointer with it's corresponding name."
echo
echo "This file is automatically generated. DO NOT MODIFY."
echo "*/"
echo "#include <string.h>"
echo "#include <stddef.h>"
echo '#include "lua.h"'
echo '#include "lauxlib.h"'
echo
echo "typedef struct fnptr_s {"
echo -e "\tconst char* name;"
echo -e "\tvoid *addr;"
echo "} fnptr_t;"
echo
echo "#define EXPORT_SYMBOL(SYM) { #SYM, (void*)(SYM) }"
echo "static void *api_require(const char *symbol) {"
echo -e "\tstatic fnptr_t nodes[] = {"
EOF
decl_export "$LUA_PATH/lua.h"
decl_export "$LUA_PATH/lauxlib.h"
cat "$0"
echo -e "\t};"
echo -e "\tfor (int i = 0; i < sizeof(nodes) / sizeof(fnptr_t); i++)"
echo -e "\t\tif (strcmp(nodes[i].name, symbol) == 0)"
echo -e "\t\t\treturn nodes[i].addr;"
echo -e "\treturn NULL;"
echo "}"
echo "#endif"
}
cat << EOF
**/
show_help() {
echo -e "Usage: $0 <OPTIONS> prefix"
echo
echo -e "Available options:"
echo
echo -e "-a\t--api-header\tGenerate lite_xl_plugin_api.h"
echo -e "-b\t--api-require\tGenerate api_require.h"
echo -e "-p\t--prefix\tSet prefix (where to find lua.h and lauxlib.h)"
}
main() {
local header=0
local require=0
local prefix=""
#ifndef LITE_XL_PLUGIN_API
#define LITE_XL_PLUGIN_API
EOF
for i in "$@"; do
case $i in
-h|--help)
show_help
exit 0
;;
-a|--api-header)
header=1
shift
;;
-b|--api-require)
require=1
shift
;;
-p|--prefix)
prefix="$2"
shift
shift
;;
*)
;;
esac
done
decl "$LUA_PATH/lua.h"
decl "$LUA_PATH/lauxlib.h"
if [[ "$header" -eq 1 ]]; then
generate_header "$prefix"
elif [[ "$require" -eq 1 ]]; then
generate_api_require "$prefix"
else
show_help
exit 1
fi
}
echo "#define IMPORT_SYMBOL(name, ret, ...) name = (ret (*) (__VA_ARGS__)) symbol(#name)"
echo "static void lite_xl_plugin_init(void *XL) {"
echo -e "\tvoid* (*symbol)(const char *) = (void* (*) (const char *)) XL;"
decl_export "$LUA_PATH/lua.h"
decl_export "$LUA_PATH/lauxlib.h"
echo "}"
echo "#endif"
main "$@"