~ubuntu-branches/ubuntu/raring/codeblocks/raring-proposed

« back to all changes in this revision

Viewing changes to src/sdk/wxscintilla/src/scintilla/src/LexMySQL.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-08-09 04:38:38 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20100809043838-a59ygguym4eg0jgw
Tags: 10.05-0ubuntu1
* New upstream release. Closes (LP: #322350)
 - Switch to dpkg-source 3.0 (quilt) format
 - Remove unneeded README.source
 - Add debian/get-source-orig script that removes all
   Windows prebuilt binaries
* Bump Standards-Version to 3.9.1
 - Stop shipping *.la files
* debian/control
 - Add cdbs package as Build-Depend
 - Add libbz2-dev and zlib1g-dev packages as
   Build-Depends (needed by libhelp_plugin.so)
 - Remove dpatch package of Build-Depends
 - Add codeblocks-contrib-debug package
 - Split architecture-independent files of codeblocks
   package in codeblocks-common package
* debian/rules
 - Switch to CDBS rules system
 - Add parallel build support
 - Add a call to debian/get-source-orig script
 - Use lzma compression (saves 23,5 MB of free space)
* debian/patches
 - Refresh 01_codeblocks_plugin_path
 - Add 02_no_Makefiles_in_debian_dir to remove any link
   in codeblocks build system to deleted Makefiles of debian directory
 - Drop 02_ftbfs_gcc44 and 03_ftbfs_glib221 (merged in upstream)
* debian/watch
 - Update to use the new host (berlios.de)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Scintilla source code edit control
 
3
 * @file LexMySQL.cxx
 
4
 * Lexer for MySQL
 
5
 *
 
6
 * Improved by Mike Lischke <mike.lischke@sun.com>
 
7
 * Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com>
 
8
 * Original work by Neil Hodgson <neilh@scintilla.org>
 
9
 * Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 
10
 * The License.txt file describes the conditions under which this software may be distributed.
 
11
 */
 
12
 
 
13
#include <stdlib.h>
 
14
#include <string.h>
 
15
#include <ctype.h>
 
16
#include <stdio.h>
 
17
#include <stdarg.h>
 
18
 
 
19
#include "Platform.h"
 
20
 
 
21
#include "PropSet.h"
 
22
#include "Accessor.h"
 
23
#include "StyleContext.h"
 
24
#include "KeyWords.h"
 
25
#include "Scintilla.h"
 
26
#include "SciLexer.h"
 
27
 
 
28
#ifdef SCI_NAMESPACE
 
29
using namespace Scintilla;
 
30
#endif
 
31
 
 
32
static inline bool IsAWordChar(int ch) {
 
33
        return (ch < 0x80) && (isalnum(ch) || ch == '_');
 
34
}
 
35
 
 
36
static inline bool IsAWordStart(int ch) {
 
37
        return (ch < 0x80) && (isalpha(ch) || ch == '_');
 
38
}
 
39
 
 
40
static inline bool IsADoxygenChar(int ch) {
 
41
        return (islower(ch) || ch == '$' || ch == '@' ||
 
42
                ch == '\\' || ch == '&' || ch == '<' ||
 
43
                ch == '>' || ch == '#' || ch == '{' ||
 
44
                ch == '}' || ch == '[' || ch == ']');
 
45
}
 
46
 
 
47
static inline bool IsANumberChar(int ch) {
 
48
        // Not exactly following number definition (several dots are seen as OK, etc.)
 
49
        // but probably enough in most cases.
 
50
        return (ch < 0x80) &&
 
51
                (isdigit(ch) || toupper(ch) == 'E' ||
 
52
             ch == '.' || ch == '-' || ch == '+');
 
53
}
 
54
 
 
55
//--------------------------------------------------------------------------------------------------
 
56
 
 
57
/**
 
58
 * Check if the current content context represent a keyword and set the context state if so.
 
59
 */
 
60
static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[])
 
61
{
 
62
  int length = sc.LengthCurrent() + 1; // +1 for the next char
 
63
  char* s = new char[length];
 
64
  sc.GetCurrentLowered(s, length);
 
65
  if (keywordlists[0]->InList(s))
 
66
    sc.ChangeState(SCE_MYSQL_MAJORKEYWORD);
 
67
  else
 
68
    if (keywordlists[1]->InList(s))
 
69
      sc.ChangeState(SCE_MYSQL_KEYWORD);
 
70
    else
 
71
      if (keywordlists[2]->InList(s))
 
72
        sc.ChangeState(SCE_MYSQL_DATABASEOBJECT);
 
73
      else
 
74
        if (keywordlists[3]->InList(s))
 
75
          sc.ChangeState(SCE_MYSQL_FUNCTION);
 
76
        else
 
77
          if (keywordlists[5]->InList(s))
 
78
            sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD);
 
79
          else
 
80
            if (keywordlists[6]->InList(s))
 
81
              sc.ChangeState(SCE_MYSQL_USER1);
 
82
            else
 
83
              if (keywordlists[7]->InList(s))
 
84
                sc.ChangeState(SCE_MYSQL_USER2);
 
85
              else
 
86
                if (keywordlists[8]->InList(s))
 
87
                  sc.ChangeState(SCE_MYSQL_USER3);
 
88
  delete [] s;
 
89
}
 
90
 
 
91
//--------------------------------------------------------------------------------------------------
 
92
 
 
93
static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
 
94
                            Accessor &styler)
 
95
{
 
96
        StyleContext sc(startPos, length, initStyle, styler);
 
97
 
 
98
        for (; sc.More(); sc.Forward())
 
99
  {
 
100
                // Determine if the current state should terminate.
 
101
                switch (sc.state)
 
102
    {
 
103
      case SCE_MYSQL_OPERATOR:
 
104
        sc.SetState(SCE_MYSQL_DEFAULT);
 
105
        break;
 
106
      case SCE_MYSQL_NUMBER:
 
107
        // We stop the number definition on non-numerical non-dot non-eE non-sign char.
 
108
        if (!IsANumberChar(sc.ch))
 
109
          sc.SetState(SCE_MYSQL_DEFAULT);
 
110
        break;
 
111
      case SCE_MYSQL_IDENTIFIER:
 
112
        // Switch from identifier to keyword state and open a new state for the new char.
 
113
        if (!IsAWordChar(sc.ch))
 
114
        {
 
115
          CheckForKeyword(sc, keywordlists);
 
116
          
 
117
          // Additional check for function keywords needed.
 
118
          // A function name must be followed by an opening parenthesis.
 
119
          if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
 
120
            sc.ChangeState(SCE_MYSQL_DEFAULT);
 
121
            
 
122
          sc.SetState(SCE_MYSQL_DEFAULT);
 
123
        }
 
124
        break;
 
125
      case SCE_MYSQL_VARIABLE:
 
126
        if (!IsAWordChar(sc.ch))
 
127
          sc.SetState(SCE_MYSQL_DEFAULT);
 
128
        break;
 
129
      case SCE_MYSQL_SYSTEMVARIABLE:
 
130
        if (!IsAWordChar(sc.ch))
 
131
        {
 
132
          int length = sc.LengthCurrent() + 1;
 
133
          char* s = new char[length];
 
134
          sc.GetCurrentLowered(s, length);
 
135
 
 
136
          // Check for known system variables here.
 
137
          if (keywordlists[4]->InList(&s[2]))
 
138
            sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE);
 
139
          delete [] s;
 
140
          
 
141
          sc.SetState(SCE_MYSQL_DEFAULT);
 
142
        }
 
143
        break;
 
144
      case SCE_MYSQL_QUOTEDIDENTIFIER:
 
145
        if (sc.ch == '`')
 
146
        {
 
147
          if (sc.chNext == '`')
 
148
            sc.Forward();       // Ignore it
 
149
          else
 
150
            sc.ForwardSetState(SCE_MYSQL_DEFAULT);
 
151
                                }
 
152
                        break;
 
153
      case SCE_MYSQL_COMMENT:
 
154
      case SCE_MYSQL_HIDDENCOMMAND:
 
155
        if (sc.Match('*', '/'))
 
156
        {
 
157
          sc.Forward();
 
158
          sc.ForwardSetState(SCE_MYSQL_DEFAULT);
 
159
        }
 
160
        break;
 
161
      case SCE_MYSQL_COMMENTLINE:
 
162
        if (sc.atLineStart)
 
163
          sc.SetState(SCE_MYSQL_DEFAULT);
 
164
        break;
 
165
      case SCE_MYSQL_SQSTRING:
 
166
        if (sc.ch == '\\')
 
167
          sc.Forward(); // Escape sequence
 
168
        else
 
169
          if (sc.ch == '\'')
 
170
          {
 
171
            // End of single quoted string reached?
 
172
            if (sc.chNext == '\'')
 
173
              sc.Forward();
 
174
            else
 
175
              sc.ForwardSetState(SCE_MYSQL_DEFAULT);
 
176
          }
 
177
        break;
 
178
      case SCE_MYSQL_DQSTRING:
 
179
        if (sc.ch == '\\')
 
180
          sc.Forward(); // Escape sequence
 
181
        else
 
182
          if (sc.ch == '\"')
 
183
          {
 
184
            // End of single quoted string reached?
 
185
            if (sc.chNext == '\"')
 
186
              sc.Forward();
 
187
            else
 
188
              sc.ForwardSetState(SCE_MYSQL_DEFAULT);
 
189
          }
 
190
        break;
 
191
    }
 
192
 
 
193
    // Determine if a new state should be entered.
 
194
    if (sc.state == SCE_MYSQL_DEFAULT)
 
195
    {
 
196
      switch (sc.ch)
 
197
      {
 
198
        case '@':
 
199
          if (sc.chNext == '@')
 
200
          {
 
201
            sc.SetState(SCE_MYSQL_SYSTEMVARIABLE);
 
202
            sc.Forward(2); // Skip past @@.
 
203
          }
 
204
          else
 
205
            if (IsAWordStart(sc.ch))
 
206
            {
 
207
              sc.SetState(SCE_MYSQL_VARIABLE);
 
208
              sc.Forward(); // Skip past @.
 
209
            }
 
210
            else
 
211
              sc.SetState(SCE_MYSQL_OPERATOR);
 
212
          break;
 
213
        case '`':
 
214
          sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER);
 
215
          break;
 
216
        case '#':
 
217
          sc.SetState(SCE_MYSQL_COMMENTLINE);
 
218
          break;
 
219
        case '\'':
 
220
          sc.SetState(SCE_MYSQL_SQSTRING);
 
221
          break;
 
222
        case '\"':
 
223
          sc.SetState(SCE_MYSQL_DQSTRING);
 
224
          break;
 
225
        default:
 
226
          if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
 
227
            sc.SetState(SCE_MYSQL_NUMBER);
 
228
          else
 
229
            if (IsAWordStart(sc.ch))
 
230
              sc.SetState(SCE_MYSQL_IDENTIFIER);
 
231
            else
 
232
              if (sc.Match('/', '*'))
 
233
              {
 
234
                sc.SetState(SCE_MYSQL_COMMENT);
 
235
                
 
236
                // Skip comment introducer and check for hidden command.
 
237
                sc.Forward(2);
 
238
                if (sc.ch == '!')
 
239
                {
 
240
                  sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
 
241
                  sc.Forward();
 
242
                }
 
243
              }
 
244
              else
 
245
                if (sc.Match("--"))
 
246
                {
 
247
                  // Special MySQL single line comment.
 
248
                  sc.SetState(SCE_MYSQL_COMMENTLINE);
 
249
                  sc.Forward(2);
 
250
                  
 
251
                  // Check the third character too. It must be a space or EOL.
 
252
                  if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r')
 
253
                    sc.ChangeState(SCE_MYSQL_OPERATOR);
 
254
                }
 
255
                else
 
256
                  if (isoperator(static_cast<char>(sc.ch)))
 
257
                    sc.SetState(SCE_MYSQL_OPERATOR);
 
258
      }
 
259
    }
 
260
  }
 
261
  
 
262
  // Do a final check for keywords if we currently have an identifier, to highlight them
 
263
  // also at the end of a line.
 
264
  if (sc.state == SCE_MYSQL_IDENTIFIER)
 
265
  {
 
266
    CheckForKeyword(sc, keywordlists);
 
267
 
 
268
    // Additional check for function keywords needed.
 
269
    // A function name must be followed by an opening parenthesis.
 
270
    if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
 
271
      sc.ChangeState(SCE_MYSQL_DEFAULT);
 
272
  }
 
273
        
 
274
  sc.Complete();
 
275
}
 
276
 
 
277
//--------------------------------------------------------------------------------------------------
 
278
 
 
279
/**
 
280
 * Helper function to determine if we have a foldable comment currently.
 
281
 */
 
282
static bool IsStreamCommentStyle(int style)
 
283
{
 
284
        return style == SCE_MYSQL_COMMENT;
 
285
}
 
286
 
 
287
//--------------------------------------------------------------------------------------------------
 
288
 
 
289
/**
 
290
 * Code copied from StyleContext and modified to work here. Should go into Accessor as a
 
291
 * companion to Match()...
 
292
 */
 
293
bool MatchIgnoreCase(Accessor &styler, int currentPos, const char *s)
 
294
{
 
295
  for (int n = 0; *s; n++)
 
296
  {
 
297
    if (*s != tolower(styler.SafeGetCharAt(currentPos + n)))
 
298
      return false;
 
299
    s++;
 
300
  }
 
301
  return true;
 
302
}
 
303
 
 
304
//--------------------------------------------------------------------------------------------------
 
305
 
 
306
// Store both the current line's fold level and the next lines in the
 
307
// level store to make it easy to pick up with each increment.
 
308
static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler)
 
309
{
 
310
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
 
311
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
 
312
        bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0;
 
313
 
 
314
        int visibleChars = 0;
 
315
        int lineCurrent = styler.GetLine(startPos);
 
316
        int levelCurrent = SC_FOLDLEVELBASE;
 
317
        if (lineCurrent > 0)
 
318
                levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
 
319
        int levelNext = levelCurrent;
 
320
 
 
321
        int styleNext = styler.StyleAt(startPos);
 
322
        int style = initStyle;
 
323
        
 
324
  bool endFound = false;
 
325
        bool whenFound = false;
 
326
        bool elseFound = false;
 
327
 
 
328
  char nextChar = styler.SafeGetCharAt(startPos);
 
329
  for (unsigned int i = startPos; length > 0; i++, length--)
 
330
  {
 
331
                int stylePrev = style;
 
332
                style = styleNext;
 
333
                styleNext = styler.StyleAt(i + 1);
 
334
    
 
335
    char currentChar = nextChar;
 
336
    nextChar = styler.SafeGetCharAt(i + 1);
 
337
                bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n');
 
338
        
 
339
    switch (style)
 
340
    {
 
341
      case SCE_MYSQL_COMMENT:
 
342
        if (foldComment)
 
343
        {
 
344
          // Multiline comment style /* .. */.
 
345
          if (IsStreamCommentStyle(style))
 
346
          {
 
347
            // Increase level if we just start a foldable comment.
 
348
            if (!IsStreamCommentStyle(stylePrev))
 
349
              levelNext++;
 
350
            else
 
351
              // If we are in the middle of a foldable comment check if it ends now.
 
352
              // Don't end at the line end, though.
 
353
              if (!IsStreamCommentStyle(styleNext) && !atEOL)
 
354
                levelNext--;
 
355
          }
 
356
        }
 
357
        break;
 
358
      case SCE_MYSQL_COMMENTLINE:
 
359
        if (foldComment)
 
360
        { 
 
361
          // Not really a standard, but we add support for single line comments
 
362
          // with special curly braces syntax as foldable comments too.
 
363
          // MySQL needs -- comments to be followed by space or control char
 
364
          if (styler.Match(i, "--"))
 
365
          {
 
366
            char chNext2 = styler.SafeGetCharAt(i + 2);
 
367
            char chNext3 = styler.SafeGetCharAt(i + 3);
 
368
            if (chNext2 == '{' || chNext3 == '{')
 
369
              levelNext++;
 
370
            else
 
371
              if (chNext2 == '}' || chNext3 == '}')
 
372
                levelNext--;
 
373
          }
 
374
        }
 
375
        break;
 
376
      case SCE_MYSQL_HIDDENCOMMAND:
 
377
        if (style != stylePrev)
 
378
          levelNext++;
 
379
        else
 
380
          if (style != styleNext)
 
381
            levelNext--;
 
382
        break;
 
383
      case SCE_MYSQL_OPERATOR:
 
384
        if (currentChar == '(')
 
385
          levelNext++;
 
386
        else
 
387
          if (currentChar == ')')
 
388
            levelNext--;
 
389
        break;
 
390
      case SCE_MYSQL_MAJORKEYWORD:
 
391
      case SCE_MYSQL_KEYWORD:
 
392
      case SCE_MYSQL_FUNCTION:
 
393
      case SCE_MYSQL_PROCEDUREKEYWORD:
 
394
        // Reserved and other keywords.
 
395
        if (style != stylePrev)
 
396
        {
 
397
          bool beginFound = MatchIgnoreCase(styler, i, "begin");
 
398
          bool ifFound = MatchIgnoreCase(styler, i, "if");
 
399
          bool thenFound = MatchIgnoreCase(styler, i, "then");
 
400
          bool whileFound = MatchIgnoreCase(styler, i, "while");
 
401
          bool loopFound = MatchIgnoreCase(styler, i, "loop");
 
402
          bool repeatFound = MatchIgnoreCase(styler, i, "repeat");
 
403
          
 
404
          if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound))
 
405
          {
 
406
            endFound = false;
 
407
            levelNext--;
 
408
            if (levelNext < SC_FOLDLEVELBASE)
 
409
              levelNext = SC_FOLDLEVELBASE;
 
410
            
 
411
            // Note that "else" is special here. It may or may not be followed by an "if .. then",
 
412
            // but in any case the level stays the same. When followed by an "if .. then" the level
 
413
            // will be increased later, if not, then at eol.
 
414
          }
 
415
          else
 
416
            if (!foldOnlyBegin && MatchIgnoreCase(styler, i, "else"))
 
417
            {
 
418
              levelNext--;
 
419
              elseFound = true;
 
420
            }
 
421
            else
 
422
              if (!foldOnlyBegin && thenFound)
 
423
              {
 
424
                if (whenFound)
 
425
                  whenFound = false;
 
426
                else
 
427
                  levelNext++;
 
428
              }
 
429
              else
 
430
                if (ifFound)
 
431
                  elseFound = false;
 
432
                else
 
433
                  if (MatchIgnoreCase(styler, i, "when"))
 
434
                    whenFound = true;
 
435
                  else
 
436
                  {
 
437
                    if (beginFound)
 
438
                      levelNext++;
 
439
                    else
 
440
                      if (!foldOnlyBegin && (loopFound || repeatFound || whileFound))
 
441
                      {
 
442
                        if (endFound)
 
443
                          endFound = false;
 
444
                        else
 
445
                          levelNext++;
 
446
                      }
 
447
                      else
 
448
                        if (MatchIgnoreCase(styler, i, "end"))
 
449
                        {
 
450
                          // Multiple "end" in a row are counted multiple times!
 
451
                          if (endFound)
 
452
                          {
 
453
                            levelNext--;
 
454
                            if (levelNext < SC_FOLDLEVELBASE)
 
455
                              levelNext = SC_FOLDLEVELBASE;
 
456
                          }
 
457
                          endFound = true;
 
458
                          whenFound = false;
 
459
                        }
 
460
                  }
 
461
        }
 
462
        break;
 
463
    }
 
464
    
 
465
    // Handle the case of a trailing end without an if / while etc, as in the case of a begin.
 
466
                if (endFound)
 
467
    {
 
468
                        endFound = false;
 
469
                        levelNext--;
 
470
                        if (levelNext < SC_FOLDLEVELBASE)
 
471
        levelNext = SC_FOLDLEVELBASE;
 
472
                }
 
473
    
 
474
                if (atEOL)
 
475
    {
 
476
                        if (elseFound)
 
477
      {
 
478
                                levelNext++;
 
479
        elseFound = false;
 
480
      }
 
481
 
 
482
                        int levelUse = levelCurrent;
 
483
                        int lev = levelUse | levelNext << 16;
 
484
                        if (visibleChars == 0 && foldCompact)
 
485
                                lev |= SC_FOLDLEVELWHITEFLAG;
 
486
                        if (levelUse < levelNext)
 
487
                                lev |= SC_FOLDLEVELHEADERFLAG;
 
488
                        if (lev != styler.LevelAt(lineCurrent))
 
489
                                styler.SetLevel(lineCurrent, lev);
 
490
      
 
491
                        lineCurrent++;
 
492
                        levelCurrent = levelNext;
 
493
                        visibleChars = 0;
 
494
                        endFound = false;
 
495
                        whenFound = false;
 
496
                }
 
497
    
 
498
                if (!isspacechar(currentChar))
 
499
                        visibleChars++;
 
500
        }
 
501
}
 
502
 
 
503
//--------------------------------------------------------------------------------------------------
 
504
 
 
505
static const char * const mysqlWordListDesc[] = {
 
506
        "Major Keywords",
 
507
        "Keywords",
 
508
        "Database Objects",
 
509
        "Functions",
 
510
        "System Variables",
 
511
        "Procedure keywords",
 
512
        "User Keywords 1",
 
513
        "User Keywords 2",
 
514
        "User Keywords 3",
 
515
        0
 
516
};
 
517
 
 
518
LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc);