184 lines
3.9 KiB
C++
184 lines
3.9 KiB
C++
// Scintilla source code edit control
|
|
/** @file ExternalLexer.cxx
|
|
** Support external lexers in DLLs.
|
|
**/
|
|
// 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 "Platform.h"
|
|
|
|
#include "ILexer.h"
|
|
#include "Scintilla.h"
|
|
#include "SciLexer.h"
|
|
|
|
#include "LexerModule.h"
|
|
#include "Catalogue.h"
|
|
#include "ExternalLexer.h"
|
|
|
|
#ifdef SCI_NAMESPACE
|
|
using namespace Scintilla;
|
|
#endif
|
|
|
|
LexerManager *LexerManager::theInstance = NULL;
|
|
|
|
//------------------------------------------
|
|
//
|
|
// ExternalLexerModule
|
|
//
|
|
//------------------------------------------
|
|
|
|
void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
|
|
fneFactory = fFactory;
|
|
fnFactory = fFactory(index);
|
|
}
|
|
|
|
//------------------------------------------
|
|
//
|
|
// LexerLibrary
|
|
//
|
|
//------------------------------------------
|
|
|
|
LexerLibrary::LexerLibrary(const char *ModuleName) {
|
|
// Initialise some members...
|
|
first = NULL;
|
|
last = NULL;
|
|
|
|
// Load the DLL
|
|
lib = DynamicLibrary::Load(ModuleName);
|
|
if (lib->IsValid()) {
|
|
m_sModuleName = 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) {
|
|
ExternalLexerModule *lex;
|
|
LexerMinder *lm;
|
|
|
|
// Find functions in the DLL
|
|
GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
|
|
GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");
|
|
|
|
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));
|
|
lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
|
|
Catalogue::AddLexerModule(lex);
|
|
|
|
// Create a LexerMinder so we don't leak the ExternalLexerModule...
|
|
lm = new LexerMinder;
|
|
lm->self = lex;
|
|
lm->next = NULL;
|
|
if (first != NULL) {
|
|
last->next = lm;
|
|
last = lm;
|
|
} else {
|
|
first = lm;
|
|
last = lm;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
next = NULL;
|
|
}
|
|
|
|
LexerLibrary::~LexerLibrary() {
|
|
Release();
|
|
delete lib;
|
|
}
|
|
|
|
void LexerLibrary::Release() {
|
|
LexerMinder *lm;
|
|
LexerMinder *lmNext;
|
|
lm = first;
|
|
while (NULL != lm) {
|
|
lmNext = lm->next;
|
|
delete lm->self;
|
|
delete lm;
|
|
lm = lmNext;
|
|
}
|
|
|
|
first = NULL;
|
|
last = NULL;
|
|
}
|
|
|
|
//------------------------------------------
|
|
//
|
|
// LexerManager
|
|
//
|
|
//------------------------------------------
|
|
|
|
/// Return the single LexerManager instance...
|
|
LexerManager *LexerManager::GetInstance() {
|
|
if (!theInstance)
|
|
theInstance = new LexerManager;
|
|
return theInstance;
|
|
}
|
|
|
|
/// Delete any LexerManager instance...
|
|
void LexerManager::DeleteInstance() {
|
|
delete theInstance;
|
|
theInstance = NULL;
|
|
}
|
|
|
|
/// protected constructor - this is a singleton...
|
|
LexerManager::LexerManager() {
|
|
first = NULL;
|
|
last = NULL;
|
|
}
|
|
|
|
LexerManager::~LexerManager() {
|
|
Clear();
|
|
}
|
|
|
|
void LexerManager::Load(const char *path) {
|
|
LoadLexerLibrary(path);
|
|
}
|
|
|
|
void LexerManager::LoadLexerLibrary(const char *module) {
|
|
for (LexerLibrary *ll = first; ll; ll= ll->next) {
|
|
if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
|
|
return;
|
|
}
|
|
LexerLibrary *lib = new LexerLibrary(module);
|
|
if (NULL != first) {
|
|
last->next = lib;
|
|
last = lib;
|
|
} else {
|
|
first = lib;
|
|
last = lib;
|
|
}
|
|
}
|
|
|
|
void LexerManager::Clear() {
|
|
if (NULL != first) {
|
|
LexerLibrary *cur = first;
|
|
LexerLibrary *next;
|
|
while (cur) {
|
|
next = cur->next;
|
|
delete cur;
|
|
cur = next;
|
|
}
|
|
first = NULL;
|
|
last = NULL;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------
|
|
//
|
|
// LexerManager
|
|
//
|
|
//------------------------------------------
|
|
|
|
LMMinder::~LMMinder() {
|
|
LexerManager::DeleteInstance();
|
|
}
|
|
|
|
LMMinder minder;
|