1 // Scintilla source code edit control
2 /** @file ExternalLexer.cxx
3 ** Support external lexers in DLLs.
5 // Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
6 // The License.txt file describes the conditions under which this software may be distributed.
20 #include "Scintilla.h"
23 #include "LexerModule.h"
24 #include "Catalogue.h"
25 #include "ExternalLexer.h"
27 using namespace Scintilla
;
29 std::unique_ptr
<LexerManager
> LexerManager::theInstance
;
31 //------------------------------------------
33 // ExternalLexerModule
35 //------------------------------------------
37 void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory
, int index
) {
38 fneFactory
= fFactory
;
39 fnFactory
= fFactory(index
);
42 //------------------------------------------
46 //------------------------------------------
48 LexerLibrary::LexerLibrary(const char *moduleName_
) {
50 lib
.reset(DynamicLibrary::Load(moduleName_
));
52 moduleName
= moduleName_
;
53 //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
54 GetLexerCountFn GetLexerCount
= (GetLexerCountFn
)(sptr_t
)lib
->FindFunction("GetLexerCount");
57 // Find functions in the DLL
58 GetLexerNameFn GetLexerName
= (GetLexerNameFn
)(sptr_t
)lib
->FindFunction("GetLexerName");
59 GetLexerFactoryFunction fnFactory
= (GetLexerFactoryFunction
)(sptr_t
)lib
->FindFunction("GetLexerFactory");
61 const int nl
= GetLexerCount();
63 for (int i
= 0; i
< nl
; i
++) {
64 // Assign a buffer for the lexer name.
65 char lexname
[100] = "";
66 GetLexerName(i
, lexname
, sizeof(lexname
));
67 ExternalLexerModule
*lex
= new ExternalLexerModule(SCLEX_AUTOMATIC
, NULL
, lexname
, NULL
);
68 // This is storing a second reference to lex in the Catalogue as well as in modules.
69 // TODO: Should use std::shared_ptr or similar to ensure allocation safety.
70 Catalogue::AddLexerModule(lex
);
72 // Remember ExternalLexerModule so we don't leak it
73 modules
.push_back(std::unique_ptr
<ExternalLexerModule
>(lex
));
75 // The external lexer needs to know how to call into its DLL to
76 // do its lexing and folding, we tell it here.
77 lex
->SetExternal(fnFactory
, i
);
83 LexerLibrary::~LexerLibrary() {
86 //------------------------------------------
90 //------------------------------------------
92 /// Return the single LexerManager instance...
93 LexerManager
*LexerManager::GetInstance() {
95 theInstance
.reset(new LexerManager
);
96 return theInstance
.get();
99 /// Delete any LexerManager instance...
100 void LexerManager::DeleteInstance() {
104 /// protected constructor - this is a singleton...
105 LexerManager::LexerManager() {
108 LexerManager::~LexerManager() {
112 void LexerManager::Load(const char *path
) {
113 for (const std::unique_ptr
<LexerLibrary
> &ll
: libraries
) {
114 if (ll
->moduleName
== path
)
117 libraries
.push_back(std::make_unique
<LexerLibrary
>(path
));
120 void LexerManager::Clear() {
124 //------------------------------------------
126 // LMMinder -- trigger to clean up at exit.
128 //------------------------------------------
130 LMMinder::~LMMinder() {
131 LexerManager::DeleteInstance();