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 # sed regex for extracting data from function signature
# if this isn't regex, idk what is # if this isn't regex, idk what is
# LUA_API (return type as \2) (function name as \3) (args as \4) # 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 # get funcptr declarations
ptrize() { 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() { export_sym() {
# don't even bother reading this again grep '^LUA' | sed -e "s/$sym_regex/\t\tEXPORT_SYMBOL(\3),/"
grep '^LUA' | sed -e "s/$sym_regex/\tIMPORT_SYMBOL(\3, \2, \4)/"
} }
decl() { decl() {
@ -47,48 +50,134 @@ decl() {
grep '^#' <<< "$header" grep '^#' <<< "$header"
} }
decl_import() {
uncomment $1 | onelineize | import_sym
}
decl_export() { decl_export() {
uncomment $1 | onelineize | export_sym uncomment $1 | onelineize | export_sym
} }
LUA_PATH="$1"
cat << EOF generate_header() {
/** local LUA_PATH="$1"
The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long echo "#ifndef LITE_XL_PLUGIN_API"
as it has an entrypoint that looks like the following, where xxxxx is the plugin name: echo "#define LITE_XL_PLUGIN_API"
#include "lite_xl_plugin_api.h" echo "/**"
int lua_open_lite_xl_xxxxx(lua_State* L, void* XL) { echo "The lite_xl plugin API is quite simple. Any shared library can be a plugin file, so long"
lite_xl_plugin_init(XL); echo "as it has an entrypoint that looks like the following, where xxxxx is the plugin name:"
... echo '#include "lite_xl_plugin_api.h"'
return 1; 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 for i in "$@"; do
#define LITE_XL_PLUGIN_API case $i in
EOF -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" if [[ "$header" -eq 1 ]]; then
decl "$LUA_PATH/lauxlib.h" 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)" main "$@"
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"