]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/stc/scintilla/src/LexMSSQL.cxx
Patch #1106564, corrects possible 100% CPU load condition.
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexMSSQL.cxx
CommitLineData
591d01be
RD
1// Scintilla source code edit control
2/** @file LexMSSQL.cxx
3 ** Lexer for MSSQL.
4 **/
5// Copyright 1998-2002 by Filip Yaghob <fy@eg.cz>
6
7
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11#include <stdio.h>
12#include <stdarg.h>
13
14#include "Platform.h"
15
16#include "PropSet.h"
17#include "Accessor.h"
18#include "KeyWords.h"
19#include "Scintilla.h"
20#include "SciLexer.h"
21
22#define KW_MSSQL_STATEMENTS 0
23#define KW_MSSQL_DATA_TYPES 1
24#define KW_MSSQL_SYSTEM_TABLES 2
25#define KW_MSSQL_GLOBAL_VARIABLES 3
26#define KW_MSSQL_FUNCTIONS 4
27#define KW_MSSQL_STORED_PROCEDURES 5
28#define KW_MSSQL_OPERATORS 6
29
30//~ val SCE_MSSQL_DEFAULT=0
31//~ val SCE_MSSQL_COMMENT=1
32//~ val SCE_MSSQL_LINE_COMMENT=2
33//~ val SCE_MSSQL_NUMBER=3
34//~ val SCE_MSSQL_STRING=4
35//~ val SCE_MSSQL_OPERATOR=5
36//~ val SCE_MSSQL_IDENTIFIER=6
37//~ val SCE_MSSQL_VARIABLE=7
38//~ val SCE_MSSQL_COLUMN_NAME=8
39//~ val SCE_MSSQL_STATEMENT=9
40//~ val SCE_MSSQL_DATATYPE=10
41//~ val SCE_MSSQL_SYSTABLE=11
42//~ val SCE_MSSQL_GLOBAL_VARIABLE=12
43//~ val SCE_MSSQL_FUNCTION=13
44//~ val SCE_MSSQL_STORED_PROCEDURE=14
45//~ val SCE_MSSQL_DEFAULT_PREF_DATATYPE 15
46//~ val SCE_MSSQL_COLUMN_NAME_2 16
47
48static bool isMSSQLOperator(char ch) {
49 if (isascii(ch) && isalnum(ch))
50 return false;
51 // '.' left out as it is used to make up numbers
52 if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
53 ch == '-' || ch == '+' || ch == '=' || ch == '|' ||
54 ch == '<' || ch == '>' || ch == '/' ||
55 ch == '!' || ch == '~' || ch == '(' || ch == ')' ||
56 ch == ',')
57 return true;
58 return false;
59}
60
61static char classifyWordSQL(unsigned int start,
62 unsigned int end,
63 WordList *keywordlists[],
64 Accessor &styler,
65 unsigned int actualState,
66 unsigned int prevState) {
67 char s[256];
68 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
69
70 WordList &kwStatements = *keywordlists[KW_MSSQL_STATEMENTS];
71 WordList &kwDataTypes = *keywordlists[KW_MSSQL_DATA_TYPES];
72 WordList &kwSystemTables = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
73 WordList &kwGlobalVariables = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
74 WordList &kwFunctions = *keywordlists[KW_MSSQL_FUNCTIONS];
75 WordList &kwStoredProcedures = *keywordlists[KW_MSSQL_STORED_PROCEDURES];
76 WordList &kwOperators = *keywordlists[KW_MSSQL_OPERATORS];
77
78 for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) {
79 s[i] = static_cast<char>(tolower(styler[start + i]));
80 s[i + 1] = '\0';
81 }
82 char chAttr = SCE_MSSQL_IDENTIFIER;
83
84 if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) {
85
86 if (kwGlobalVariables.InList(&s[2]))
87 chAttr = SCE_MSSQL_GLOBAL_VARIABLE;
88
89 } else if (wordIsNumber) {
90 chAttr = SCE_MSSQL_NUMBER;
91
92 } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
93 // Look first in datatypes
94 if (kwDataTypes.InList(s))
95 chAttr = SCE_MSSQL_DATATYPE;
96 else if (kwOperators.InList(s))
97 chAttr = SCE_MSSQL_OPERATOR;
98 else if (kwStatements.InList(s))
99 chAttr = SCE_MSSQL_STATEMENT;
100 else if (kwSystemTables.InList(s))
101 chAttr = SCE_MSSQL_SYSTABLE;
102 else if (kwFunctions.InList(s))
103 chAttr = SCE_MSSQL_FUNCTION;
104 else if (kwStoredProcedures.InList(s))
105 chAttr = SCE_MSSQL_STORED_PROCEDURE;
106
107 } else {
108 if (kwOperators.InList(s))
109 chAttr = SCE_MSSQL_OPERATOR;
110 else if (kwStatements.InList(s))
111 chAttr = SCE_MSSQL_STATEMENT;
112 else if (kwSystemTables.InList(s))
113 chAttr = SCE_MSSQL_SYSTABLE;
114 else if (kwFunctions.InList(s))
115 chAttr = SCE_MSSQL_FUNCTION;
116 else if (kwStoredProcedures.InList(s))
117 chAttr = SCE_MSSQL_STORED_PROCEDURE;
118 else if (kwDataTypes.InList(s))
119 chAttr = SCE_MSSQL_DATATYPE;
120 }
121
122 styler.ColourTo(end, chAttr);
123
124 return chAttr;
125}
126
127static void ColouriseMSSQLDoc(unsigned int startPos, int length,
128 int initStyle, WordList *keywordlists[], Accessor &styler) {
129
130
131 styler.StartAt(startPos);
132
133 bool fold = styler.GetPropertyInt("fold") != 0;
134 int lineCurrent = styler.GetLine(startPos);
135 int spaceFlags = 0;
136/*
137 WordList &kwStatements = *keywordlists[KW_MSSQL_STATEMENTS];
138 WordList &kwDataTypes = *keywordlists[KW_MSSQL_DATA_TYPES];
139 WordList &kwSystemTables = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
140 WordList &kwGlobalVariables = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
141 WordList &kwFunctions = *keywordlists[KW_MSSQL_FUNCTIONS];
142
143 char s[100];
144 int iixx = 0;
145 s[0] = 's'; s[1] = 'e'; s[2] = 'l'; s[3] = 'e'; s[4] = 'c'; s[5] = 't'; s[6] = 0;
146 if (kwStatements.InList(s))
147 iixx = 1;
148 s[0] = 's'; s[1] = 'e'; s[2] = 'r'; s[3] = 'v'; s[4] = 'e'; s[5] = 'r'; s[6] = 'n'; s[7] = 'a'; s[8] = 'm'; s[9] = 'e'; s[10] = 0;
149 if (kwGlobalVariables.InList(s))
150 iixx += 2;
151*/
152 int state = initStyle;
153 int prevState = initStyle;
154 char chPrev = ' ';
155 char chNext = styler[startPos];
156 styler.StartSegment(startPos);
157 unsigned int lengthDoc = startPos + length;
158 for (unsigned int i = startPos; i < lengthDoc; i++) {
159 char ch = chNext;
160 chNext = styler.SafeGetCharAt(i + 1);
161
162 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
163 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
164 int lev = indentCurrent;
165 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
166 // Only non whitespace lines can be headers
167 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
168 if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
169 lev |= SC_FOLDLEVELHEADERFLAG;
170 }
171 }
172 if (fold) {
173 styler.SetLevel(lineCurrent, lev);
174 }
175 }
176
177 if (styler.IsLeadByte(ch)) {
178 chNext = styler.SafeGetCharAt(i + 2);
179 chPrev = ' ';
180 i += 1;
181 continue;
182 }
183
184 // When the last char isn't part of the state (have to deal with it too)...
185 if ( (state == SCE_MSSQL_IDENTIFIER) ||
186 (state == SCE_MSSQL_STORED_PROCEDURE) ||
187 (state == SCE_MSSQL_DATATYPE) ||
188 //~ (state == SCE_MSSQL_COLUMN_NAME) ||
189 (state == SCE_MSSQL_FUNCTION) ||
190 //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) ||
191 (state == SCE_MSSQL_VARIABLE)) {
192 if (!iswordchar(ch)) {
193 int stateTmp;
194
195 if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) {
196 styler.ColourTo(i - 1, state);
197 stateTmp = state;
198 } else
199 stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
200
201 prevState = state;
202
203 if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE)
204 state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
205 else
206 state = SCE_MSSQL_DEFAULT;
207 }
208 } else if (state == SCE_MSSQL_LINE_COMMENT) {
209 if (ch == '\r' || ch == '\n') {
210 styler.ColourTo(i - 1, state);
211 prevState = state;
212 state = SCE_MSSQL_DEFAULT;
213 }
214 } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) {
215 if ((ch != '@') && !iswordchar(ch)) {
216 classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
217 prevState = state;
218 state = SCE_MSSQL_DEFAULT;
219 }
220 }
221
222 // If is the default or one of the above succeeded
223 if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
224 if (iswordstart(ch)) {
225 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
226 prevState = state;
227 state = SCE_MSSQL_IDENTIFIER;
228 } else if (ch == '/' && chNext == '*') {
229 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
230 prevState = state;
231 state = SCE_MSSQL_COMMENT;
232 } else if (ch == '-' && chNext == '-') {
233 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
234 prevState = state;
235 state = SCE_MSSQL_LINE_COMMENT;
236 } else if (ch == '\'') {
237 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
238 prevState = state;
239 state = SCE_MSSQL_STRING;
240 } else if (ch == '"') {
241 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
242 prevState = state;
243 state = SCE_MSSQL_COLUMN_NAME;
244 } else if (ch == '[') {
245 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
246 prevState = state;
247 state = SCE_MSSQL_COLUMN_NAME_2;
248 } else if (isMSSQLOperator(ch)) {
249 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
250 styler.ColourTo(i, SCE_MSSQL_OPERATOR);
251 //~ style = SCE_MSSQL_DEFAULT;
252 prevState = state;
253 state = SCE_MSSQL_DEFAULT;
254 } else if (ch == '@') {
255 styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
256 prevState = state;
257 if (chNext == '@') {
258 state = SCE_MSSQL_GLOBAL_VARIABLE;
259// i += 2;
260 } else
261 state = SCE_MSSQL_VARIABLE;
262 }
263
264
265 // When the last char is part of the state...
266 } else if (state == SCE_MSSQL_COMMENT) {
267 if (ch == '/' && chPrev == '*') {
268 if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) &&
269 (styler.GetStartSegment() == startPos)))) {
270 styler.ColourTo(i, state);
271 //~ state = SCE_MSSQL_COMMENT;
272 prevState = state;
273 state = SCE_MSSQL_DEFAULT;
274 }
275 }
276 } else if (state == SCE_MSSQL_STRING) {
277 if (ch == '\'') {
278 if ( chNext == '\'' ) {
279 i++;
280 ch = chNext;
281 chNext = styler.SafeGetCharAt(i + 1);
282 } else {
283 styler.ColourTo(i, state);
284 prevState = state;
285 state = SCE_MSSQL_DEFAULT;
286 //i++;
287 }
288 //ch = chNext;
289 //chNext = styler.SafeGetCharAt(i + 1);
290 }
291 } else if (state == SCE_MSSQL_COLUMN_NAME) {
292 if (ch == '"') {
293 if (chNext == '"') {
294 i++;
295 ch = chNext;
296 chNext = styler.SafeGetCharAt(i + 1);
297 } else {
298 styler.ColourTo(i, state);
299 prevState = state;
300 state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
301 //i++;
302 }
303 }
304 } else if (state == SCE_MSSQL_COLUMN_NAME_2) {
305 if (ch == ']') {
306 styler.ColourTo(i, state);
307 prevState = state;
308 state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
309 //i++;
310 }
311 }
312
313 chPrev = ch;
314 }
315 styler.ColourTo(lengthDoc - 1, state);
316}
317
318static const char * const sqlWordListDesc[] = {
319 "Statements",
320 "Data Types",
321 "System tables",
322 "Global variables",
323 "Functions",
324 "System Stored Procedures",
325 "Operators",
326 0,
327};
328
329LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", 0, sqlWordListDesc);