blob: 0326f19de5b068371cb6052b93dbdd644da41e6b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
// Scintilla source code edit control
/** @file ExternalLexer.cxx
** Support external lexers in DLLs or shared libraries.
**/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>
#include <memory>
#include "Platform.h"
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "LexerModule.h"
#include "Catalogue.h"
#include "ExternalLexer.h"
using namespace Scintilla;
std::unique_ptr<LexerManager> LexerManager::theInstance;
//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------
void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
fneFactory = fFactory;
fnFactory = fFactory(index);
}
//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------
LexerLibrary::LexerLibrary(const char *moduleName_) {
// Load the DLL
lib.reset(DynamicLibrary::Load(moduleName_));
if (lib->IsValid()) {
moduleName = moduleName_;
//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");
if (GetLexerCount) {
// Find functions in the DLL
GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");
const int nl = GetLexerCount();
for (int i = 0; i < nl; i++) {
// Assign a buffer for the lexer name.
char lexname[100] = "";
GetLexerName(i, lexname, sizeof(lexname));
ExternalLexerModule *lex = new ExternalLexerModule(SCLEX_AUTOMATIC, nullptr, lexname, nullptr);
// This is storing a second reference to lex in the Catalogue as well as in modules.
// TODO: Should use std::shared_ptr or similar to ensure allocation safety.
Catalogue::AddLexerModule(lex);
// Remember ExternalLexerModule so we don't leak it
modules.push_back(std::unique_ptr<ExternalLexerModule>(lex));
// The external lexer needs to know how to call into its DLL to
// do its lexing and folding, we tell it here.
lex->SetExternal(fnFactory, i);
}
}
}
}
LexerLibrary::~LexerLibrary() {
}
//------------------------------------------
//
// LexerManager
//
//------------------------------------------
/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
if (!theInstance)
theInstance.reset(new LexerManager);
return theInstance.get();
}
/// Delete any LexerManager instance...
void LexerManager::DeleteInstance() {
theInstance.reset();
}
/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
}
LexerManager::~LexerManager() {
Clear();
}
void LexerManager::Load(const char *path) {
for (const std::unique_ptr<LexerLibrary> &ll : libraries) {
if (ll->moduleName == path)
return;
}
libraries.push_back(std::make_unique<LexerLibrary>(path));
}
void LexerManager::Clear() {
libraries.clear();
}
//------------------------------------------
//
// LMMinder -- trigger to clean up at exit.
//
//------------------------------------------
LMMinder::~LMMinder() {
LexerManager::DeleteInstance();
}
LMMinder minder;
|