]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/ExternalLexer.cxx
Cast to void* before casting to Node** to make the compiler do no strict-aliasing...
[wxWidgets.git] / contrib / src / stc / scintilla / src / ExternalLexer.cxx
1 // Scintilla source code edit control
2 /** @file ExternalLexer.cxx
3 ** Support external lexers in DLLs.
4 **/
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.
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 #include "Platform.h"
14
15 #include "SciLexer.h"
16 #include "PropSet.h"
17 #include "Accessor.h"
18 #include "DocumentAccessor.h"
19 #include "KeyWords.h"
20 #include "ExternalLexer.h"
21
22 LexerManager *LexerManager::theInstance = NULL;
23
24 //------------------------------------------
25 //
26 // ExternalLexerModule
27 //
28 //------------------------------------------
29
30 char **WordListsToStrings(WordList *val[]) {
31 int dim = 0;
32 while (val[dim])
33 dim++;
34 char **wls = new char * [dim + 1];
35 for (int i = 0;i < dim;i++) {
36 SString words;
37 words = "";
38 for (int n = 0; n < val[i]->len; n++) {
39 words += val[i]->words[n];
40 if (n != val[i]->len - 1)
41 words += " ";
42 }
43 wls[i] = new char[words.length() + 1];
44 strcpy(wls[i], words.c_str());
45 }
46 wls[dim] = 0;
47 return wls;
48 }
49
50 void DeleteWLStrings(char *strs[]) {
51 int dim = 0;
52 while (strs[dim]) {
53 delete strs[dim];
54 dim++;
55 }
56 delete [] strs;
57 }
58
59 void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
60 WordList *keywordlists[], Accessor &styler) const {
61 if (!fneLexer)
62 return ;
63
64 char **kwds = WordListsToStrings(keywordlists);
65 char *ps = styler.GetProperties();
66
67 // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
68 // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
69 DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
70 WindowID wID = da.GetWindow();
71
72 fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
73
74 delete ps;
75 DeleteWLStrings(kwds);
76 }
77
78 void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
79 WordList *keywordlists[], Accessor &styler) const {
80 if (!fneFolder)
81 return ;
82
83 char **kwds = WordListsToStrings(keywordlists);
84 char *ps = styler.GetProperties();
85
86 // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
87 // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
88 DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
89 WindowID wID = da.GetWindow();
90
91 fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
92
93 delete ps;
94 DeleteWLStrings(kwds);
95 }
96
97 void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
98 fneLexer = fLexer;
99 fneFolder = fFolder;
100 externalLanguage = index;
101 }
102
103 //------------------------------------------
104 //
105 // LexerLibrary
106 //
107 //------------------------------------------
108
109 LexerLibrary::LexerLibrary(const char* ModuleName) {
110 // Initialise some members...
111 first = NULL;
112 last = NULL;
113
114 // Load the DLL
115 lib = DynamicLibrary::Load(ModuleName);
116 if (lib->IsValid()) {
117 m_sModuleName = ModuleName;
118 //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
119 GetLexerCountFn GetLexerCount = (GetLexerCountFn)lib->FindFunction("GetLexerCount");
120
121 if (GetLexerCount) {
122 ExternalLexerModule *lex;
123 LexerMinder *lm;
124
125 // Find functions in the DLL
126 GetLexerNameFn GetLexerName = (GetLexerNameFn)lib->FindFunction("GetLexerName");
127 ExtLexerFunction Lexer = (ExtLexerFunction)lib->FindFunction("Lex");
128 ExtFoldFunction Folder = (ExtFoldFunction)lib->FindFunction("Fold");
129
130 // Assign a buffer for the lexer name.
131 char lexname[100];
132 strcpy(lexname, "");
133
134 int nl = GetLexerCount();
135
136 for (int i = 0; i < nl; i++) {
137 GetLexerName(i, lexname, 100);
138 lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
139
140 // Create a LexerMinder so we don't leak the ExternalLexerModule...
141 lm = new LexerMinder;
142 lm->self = lex;
143 lm->next = NULL;
144 if (first != NULL) {
145 last->next = lm;
146 last = lm;
147 } else {
148 first = lm;
149 last = lm;
150 }
151
152 // The external lexer needs to know how to call into its DLL to
153 // do its lexing and folding, we tell it here. Folder may be null.
154 lex->SetExternal(Lexer, Folder, i);
155 }
156 }
157 }
158 next = NULL;
159 }
160
161 LexerLibrary::~LexerLibrary() {
162 Release();
163 delete lib;
164 }
165
166 void LexerLibrary::Release() {
167 //TODO maintain a list of lexers created, and delete them!
168 LexerMinder *lm;
169 LexerMinder *next;
170 lm = first;
171 while (NULL != lm) {
172 next = lm->next;
173 delete lm->self;
174 delete lm;
175 lm = next;
176 }
177
178 first = NULL;
179 last = NULL;
180 }
181
182 //------------------------------------------
183 //
184 // LexerManager
185 //
186 //------------------------------------------
187
188 /// Return the single LexerManager instance...
189 LexerManager *LexerManager::GetInstance() {
190 if(!theInstance)
191 theInstance = new LexerManager;
192 return theInstance;
193 }
194
195 /// Delete any LexerManager instance...
196 void LexerManager::DeleteInstance()
197 {
198 if(theInstance) {
199 delete theInstance;
200 theInstance = NULL;
201 }
202 }
203
204 /// protected constructor - this is a singleton...
205 LexerManager::LexerManager() {
206 first = NULL;
207 last = NULL;
208 }
209
210 LexerManager::~LexerManager() {
211 Clear();
212 }
213
214 void LexerManager::Load(const char* path)
215 {
216 LoadLexerLibrary(path);
217 }
218
219 void LexerManager::LoadLexerLibrary(const char* module)
220 {
221 LexerLibrary *lib = new LexerLibrary(module);
222 if (NULL != first) {
223 last->next = lib;
224 last = lib;
225 } else {
226 first = lib;
227 last = lib;
228 }
229 }
230
231 void LexerManager::Clear()
232 {
233 if (NULL != first) {
234 LexerLibrary *cur = first;
235 LexerLibrary *next;
236 while (cur) {
237 next = cur->next;
238 delete cur;
239 cur = next;
240 }
241 first = NULL;
242 last = NULL;
243 }
244 }
245
246 //------------------------------------------
247 //
248 // LexerManager
249 //
250 //------------------------------------------
251
252 LMMinder::~LMMinder()
253 {
254 LexerManager::DeleteInstance();
255 }
256
257 LMMinder minder;