aboutsummaryrefslogtreecommitdiffhomepage
path: root/lexilla/test/LexillaAccess.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'lexilla/test/LexillaAccess.cxx')
-rw-r--r--lexilla/test/LexillaAccess.cxx95
1 files changed, 95 insertions, 0 deletions
diff --git a/lexilla/test/LexillaAccess.cxx b/lexilla/test/LexillaAccess.cxx
new file mode 100644
index 000000000..ea62c9605
--- /dev/null
+++ b/lexilla/test/LexillaAccess.cxx
@@ -0,0 +1,95 @@
+// Scintilla source code edit control
+/** @file LexillaAccess.cxx
+ ** Interface to Lexilla shared library.
+ **/
+ // Copyright 2019 by Neil Hodgson <neilh@scintilla.org>
+ // The License.txt file describes the conditions under which this software may be distributed.
+
+#include <cstring>
+
+#include <iterator>
+
+#include <iostream>
+#include <filesystem>
+
+#if !_WIN32
+#include <dlfcn.h>
+#else
+#include <windows.h>
+#endif
+
+#include "ILexer.h"
+
+#include "Lexilla.h"
+
+#include "LexillaAccess.h"
+
+#if _WIN32
+#define EXT_LEXER_DECL __stdcall
+typedef FARPROC Function;
+typedef HMODULE Module;
+#else
+#define EXT_LEXER_DECL
+typedef void *Function;
+typedef void *Module;
+#endif
+
+typedef Scintilla::ILexer5 *(EXT_LEXER_DECL *CreateLexerFn)(const char *name);
+
+Module lexillaDL {};
+
+/// Generic function to convert from a Function(void* or FARPROC) to a function pointer.
+/// This avoids undefined and conditionally defined behaviour.
+template<typename T>
+T FunctionPointer(Function function) noexcept {
+ static_assert(sizeof(T) == sizeof(function));
+ T fp;
+ memcpy(&fp, &function, sizeof(T));
+ return fp;
+}
+
+CreateLexerFn fnCL;
+
+Function FindSymbol(const char *symbol) noexcept {
+#if _WIN32
+ return ::GetProcAddress(lexillaDL, symbol);
+#else
+ return dlsym(lexillaDL, symbol);
+#endif
+}
+
+Scintilla::ILexer5 *CreateLexer(std::string languageName) {
+#ifdef LEXILLA_STATIC
+ return CreateLexer(languageName.c_str());
+#else
+ return fnCL(languageName.c_str());
+#endif
+}
+
+bool LoadLexilla([[maybe_unused]] std::filesystem::path path) {
+#ifdef LEXILLA_STATIC
+ return true;
+#else
+ std::filesystem::path sharedLibrary = path;
+ sharedLibrary.append("bin");
+#if _WIN32
+ sharedLibrary.append("lexilla.dll");
+ lexillaDL = ::LoadLibraryW(sharedLibrary.c_str());
+#else
+#if defined(__APPLE__)
+ sharedLibrary.append("lexilla.dylib");
+#else
+ sharedLibrary.append("lexilla.so");
+#endif
+ lexillaDL = dlopen(sharedLibrary.c_str(), RTLD_LAZY);
+#endif
+
+ if (lexillaDL) {
+ fnCL = FunctionPointer<CreateLexerFn>(FindSymbol("CreateLexer"));
+ } else {
+ std::cout << "Cannot load " << sharedLibrary.string() << "\n";
+ }
+
+ return lexillaDL && fnCL;
+#endif
+}