fix build under newer KConfig by bump cmake min version
This commit is contained in:
285
3rdparty/lexilla540/lexilla/access/LexillaAccess.cxx
vendored
Normal file
285
3rdparty/lexilla540/lexilla/access/LexillaAccess.cxx
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
// SciTE - Scintilla based Text Editor
|
||||
/** @file LexillaAccess.cxx
|
||||
** Interface to loadable lexers.
|
||||
** Maintains a list of lexer library paths and CreateLexer functions.
|
||||
** If list changes then load all the lexer libraries and find the functions.
|
||||
** When asked to create a lexer, call each function until one succeeds.
|
||||
**/
|
||||
// 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 <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "ILexer.h"
|
||||
|
||||
#include "Lexilla.h"
|
||||
|
||||
#include "LexillaAccess.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(_WIN32)
|
||||
typedef FARPROC Function;
|
||||
typedef HMODULE Module;
|
||||
constexpr const char *pathSeparator = "\\";
|
||||
#else
|
||||
typedef void *Function;
|
||||
typedef void *Module;
|
||||
constexpr const char *pathSeparator = "/";
|
||||
#endif
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
std::wstring WideStringFromUTF8(std::string_view sv) {
|
||||
const int sLength = static_cast<int>(sv.length());
|
||||
const int cchWide = ::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, nullptr, 0);
|
||||
std::wstring sWide(cchWide, 0);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, sWide.data(), cchWide);
|
||||
return sWide;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Turn off deprecation checks as LexillaAccess deprecates its wrapper over
|
||||
// the deprecated LexerNameFromID. Thus use within LexillaAccess is intentional.
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else
|
||||
#pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
std::string directoryLoadDefault;
|
||||
std::string lastLoaded;
|
||||
|
||||
struct LexLibrary {
|
||||
Lexilla::CreateLexerFn fnCL;
|
||||
Lexilla::LexerNameFromIDFn fnLNFI;
|
||||
Lexilla::GetLibraryPropertyNamesFn fnGLPN;
|
||||
Lexilla::SetLibraryPropertyFn fnSLP;
|
||||
std::string nameSpace;
|
||||
};
|
||||
std::vector<LexLibrary> libraries;
|
||||
|
||||
std::vector<std::string> lexers;
|
||||
std::vector<std::string> libraryProperties;
|
||||
|
||||
Function FindSymbol(Module m, const char *symbol) noexcept {
|
||||
#if defined(_WIN32)
|
||||
return ::GetProcAddress(m, symbol);
|
||||
#else
|
||||
return dlsym(m, symbol);
|
||||
#endif
|
||||
}
|
||||
|
||||
Lexilla::CreateLexerFn pCreateLexerDefault = nullptr;
|
||||
|
||||
bool NameContainsDot(std::string_view path) noexcept {
|
||||
for (std::string_view::const_reverse_iterator it = path.crbegin();
|
||||
it != path.crend(); ++it) {
|
||||
if (*it == '.')
|
||||
return true;
|
||||
if (*it == '/' || *it == '\\')
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool HasPrefix(std::string_view s, std::string_view prefix) noexcept {
|
||||
return (s.size() >= prefix.size()) && (prefix == s.substr(0, prefix.size()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Lexilla::SetDefault(CreateLexerFn pCreate) noexcept {
|
||||
pCreateLexerDefault = pCreate;
|
||||
}
|
||||
|
||||
void Lexilla::SetDefaultDirectory(std::string_view directory) {
|
||||
directoryLoadDefault = directory;
|
||||
}
|
||||
|
||||
bool Lexilla::Load(std::string_view sharedLibraryPaths) {
|
||||
if (sharedLibraryPaths == lastLoaded) {
|
||||
return !libraries.empty();
|
||||
}
|
||||
|
||||
std::string_view paths = sharedLibraryPaths;
|
||||
lexers.clear();
|
||||
|
||||
libraries.clear();
|
||||
while (!paths.empty()) {
|
||||
const size_t separator = paths.find_first_of(';');
|
||||
std::string path(paths.substr(0, separator));
|
||||
if (separator == std::string::npos) {
|
||||
paths.remove_prefix(paths.size());
|
||||
} else {
|
||||
paths.remove_prefix(separator + 1);
|
||||
}
|
||||
if (path == ".") {
|
||||
if (directoryLoadDefault.empty()) {
|
||||
path = "";
|
||||
} else {
|
||||
path = directoryLoadDefault;
|
||||
path += pathSeparator;
|
||||
}
|
||||
path += LEXILLA_LIB;
|
||||
}
|
||||
if (!NameContainsDot(path)) {
|
||||
// No '.' in name so add extension
|
||||
path.append(LEXILLA_EXTENSION);
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
// Convert from UTF-8 to wide characters
|
||||
std::wstring wsPath = WideStringFromUTF8(path);
|
||||
Module lexillaDL = ::LoadLibraryW(wsPath.c_str());
|
||||
#else
|
||||
Module lexillaDL = dlopen(path.c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
if (lexillaDL) {
|
||||
GetLexerCountFn fnLexerCount = FunctionPointer<GetLexerCountFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_GETLEXERCOUNT));
|
||||
GetLexerNameFn fnLexerName = FunctionPointer<GetLexerNameFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_GETLEXERNAME));
|
||||
if (fnLexerCount && fnLexerName) {
|
||||
const int nLexers = fnLexerCount();
|
||||
for (int i = 0; i < nLexers; i++) {
|
||||
char name[100] = "";
|
||||
fnLexerName(i, name, sizeof(name));
|
||||
lexers.push_back(name);
|
||||
}
|
||||
}
|
||||
CreateLexerFn fnCL = FunctionPointer<CreateLexerFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_CREATELEXER));
|
||||
LexerNameFromIDFn fnLNFI = FunctionPointer<LexerNameFromIDFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_LEXERNAMEFROMID));
|
||||
GetLibraryPropertyNamesFn fnGLPN = FunctionPointer<GetLibraryPropertyNamesFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_GETLIBRARYPROPERTYNAMES));
|
||||
SetLibraryPropertyFn fnSLP = FunctionPointer<SetLibraryPropertyFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_SETLIBRARYPROPERTY));
|
||||
GetNameSpaceFn fnGNS = FunctionPointer<GetNameSpaceFn>(
|
||||
FindSymbol(lexillaDL, LEXILLA_GETNAMESPACE));
|
||||
std::string nameSpace;
|
||||
if (fnGNS) {
|
||||
nameSpace = fnGNS();
|
||||
nameSpace += LEXILLA_NAMESPACE_SEPARATOR;
|
||||
}
|
||||
LexLibrary lexLib {
|
||||
fnCL,
|
||||
fnLNFI,
|
||||
fnGLPN,
|
||||
fnSLP,
|
||||
nameSpace
|
||||
};
|
||||
libraries.push_back(lexLib);
|
||||
}
|
||||
}
|
||||
lastLoaded = sharedLibraryPaths;
|
||||
|
||||
std::set<std::string> nameSet;
|
||||
for (const LexLibrary &lexLib : libraries) {
|
||||
if (lexLib.fnGLPN) {
|
||||
const char *cpNames = lexLib.fnGLPN();
|
||||
if (cpNames) {
|
||||
std::string_view names = cpNames;
|
||||
while (!names.empty()) {
|
||||
const size_t separator = names.find_first_of('\n');
|
||||
std::string name(names.substr(0, separator));
|
||||
nameSet.insert(name);
|
||||
if (separator == std::string::npos) {
|
||||
names.remove_prefix(names.size());
|
||||
} else {
|
||||
names.remove_prefix(separator + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Standard Lexilla does not have any properties so can't be added to set.
|
||||
libraryProperties = std::vector<std::string>(nameSet.begin(), nameSet.end());
|
||||
|
||||
return !libraries.empty();
|
||||
}
|
||||
|
||||
Scintilla::ILexer5 *Lexilla::MakeLexer(std::string_view languageName) {
|
||||
std::string sLanguageName(languageName); // Ensure NUL-termination
|
||||
// First, try to match namespace then name suffix
|
||||
for (const LexLibrary &lexLib : libraries) {
|
||||
if (lexLib.fnCL && !lexLib.nameSpace.empty()) {
|
||||
if (HasPrefix(languageName, lexLib.nameSpace)) {
|
||||
Scintilla::ILexer5 *pLexer = lexLib.fnCL(sLanguageName.substr(lexLib.nameSpace.size()).c_str());
|
||||
if (pLexer) {
|
||||
return pLexer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If no match with namespace, try to just match name
|
||||
for (const LexLibrary &lexLib : libraries) {
|
||||
if (lexLib.fnCL) {
|
||||
Scintilla::ILexer5 *pLexer = lexLib.fnCL(sLanguageName.c_str());
|
||||
if (pLexer) {
|
||||
return pLexer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pCreateLexerDefault) {
|
||||
return pCreateLexerDefault(sLanguageName.c_str());
|
||||
}
|
||||
#if defined(LEXILLA_STATIC)
|
||||
Scintilla::ILexer5 *pLexer = CreateLexer(sLanguageName.c_str());
|
||||
if (pLexer) {
|
||||
return pLexer;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> Lexilla::Lexers() {
|
||||
return lexers;
|
||||
}
|
||||
|
||||
std::string Lexilla::NameFromID(int identifier) {
|
||||
for (const LexLibrary &lexLib : libraries) {
|
||||
if (lexLib.fnLNFI) {
|
||||
const char *name = lexLib.fnLNFI(identifier);
|
||||
if (name) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::vector<std::string> Lexilla::LibraryProperties() {
|
||||
return libraryProperties;
|
||||
}
|
||||
|
||||
void Lexilla::SetProperty(const char *key, const char *value) {
|
||||
for (const LexLibrary &lexLib : libraries) {
|
||||
if (lexLib.fnSLP) {
|
||||
lexLib.fnSLP(key, value);
|
||||
}
|
||||
}
|
||||
// Standard Lexilla does not have any properties so don't set.
|
||||
}
|
35
3rdparty/lexilla540/lexilla/access/LexillaAccess.h
vendored
Normal file
35
3rdparty/lexilla540/lexilla/access/LexillaAccess.h
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// SciTE - Scintilla based Text Editor
|
||||
/** @file LexillaAccess.h
|
||||
** Interface to loadable lexers.
|
||||
** This does not depend on SciTE code so can be copied out into other projects.
|
||||
**/
|
||||
// Copyright 2019 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef LEXILLAACCESS_H
|
||||
#define LEXILLAACCESS_H
|
||||
|
||||
namespace Lexilla {
|
||||
|
||||
// Directory to load default Lexilla from, commonly the directory of the application.
|
||||
void SetDefaultDirectory(std::string_view directory);
|
||||
|
||||
// Specify CreateLexer when statically linked so no hard dependency in LexillaAccess
|
||||
// so it doesn't have to be built in two forms - static and dynamic.
|
||||
void SetDefault(CreateLexerFn pCreate) noexcept;
|
||||
|
||||
// sharedLibraryPaths is a ';' separated list of shared libraries to load.
|
||||
// On Win32 it is treated as UTF-8 and on Unix it is passed to dlopen directly.
|
||||
// Return true if any shared libraries are loaded.
|
||||
bool Load(std::string_view sharedLibraryPaths);
|
||||
|
||||
Scintilla::ILexer5 *MakeLexer(std::string_view languageName);
|
||||
|
||||
std::vector<std::string> Lexers();
|
||||
[[deprecated]] std::string NameFromID(int identifier);
|
||||
std::vector<std::string> LibraryProperties();
|
||||
void SetProperty(const char *key, const char *value);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
9
3rdparty/lexilla540/lexilla/access/README
vendored
Normal file
9
3rdparty/lexilla540/lexilla/access/README
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
README for access directory.
|
||||
|
||||
LexillaAccess is a module that simplifies using multiple libraries that follow the Lexilla protocol.
|
||||
|
||||
It can be compiled into a Lexilla client application.
|
||||
|
||||
Applications with complex needs can copy the code and customise it to meet their requirements.
|
||||
|
||||
This module is not meant to be compiled into Lexilla.
|
Reference in New Issue
Block a user