1 // Scintilla source code edit control
2 /** @file LexCrontab.cxx
3 ** Lexer to use with extended crontab files used by a powerful
4 ** Windows scheduler/event monitor/automation manager nnCron.
5 ** (http://nemtsev.virtualave.net/)
7 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
8 // The License.txt file describes the conditions under which this software may be distributed.
21 #include "Scintilla.h"
24 static void ColouriseNncrontabDoc(unsigned int startPos
, int length
, int, WordList
25 *keywordLists
[], Accessor
&styler
)
27 int state
= SCE_NNCRONTAB_DEFAULT
;
28 char chNext
= styler
[startPos
];
29 int lengthDoc
= startPos
+ length
;
30 // create a buffer large enough to take the largest chunk...
31 char *buffer
= new char[length
];
33 // used when highliting environment variables inside quoted string:
34 bool insideString
= false;
36 // this assumes that we have 3 keyword list in conf.properties
37 WordList
§ion
= *keywordLists
[0];
38 WordList
&keyword
= *keywordLists
[1];
39 WordList
&modifier
= *keywordLists
[2];
41 // go through all provided text segment
42 // using the hand-written state machine shown below
43 styler
.StartAt(startPos
);
44 styler
.StartSegment(startPos
);
45 for (int i
= startPos
; i
< lengthDoc
; i
++) {
47 chNext
= styler
.SafeGetCharAt(i
+ 1);
49 if (styler
.IsLeadByte(ch
)) {
50 chNext
= styler
.SafeGetCharAt(i
+ 2);
55 case SCE_NNCRONTAB_DEFAULT
:
56 if( ch
== '\n' || ch
== '\r' || ch
== '\t' || ch
== ' ') {
57 // whitespace is simply ignored here...
58 styler
.ColourTo(i
,SCE_NNCRONTAB_DEFAULT
);
60 } else if( ch
== '#' && styler
.SafeGetCharAt(i
+1) == '(') {
61 // signals the start of a task...
62 state
= SCE_NNCRONTAB_TASK
;
63 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
65 else if( ch
== '\\' && styler
.SafeGetCharAt(i
+1) == ' ') {
66 // signals the start of an extended comment...
67 state
= SCE_NNCRONTAB_COMMENT
;
68 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
69 } else if( ch
== '#' ) {
70 // signals the start of a plain comment...
71 state
= SCE_NNCRONTAB_COMMENT
;
72 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
73 } else if( ch
== ')' && styler
.SafeGetCharAt(i
+1) == '#') {
74 // signals the end of a task...
75 state
= SCE_NNCRONTAB_TASK
;
76 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
77 } else if( ch
== '"') {
78 state
= SCE_NNCRONTAB_STRING
;
79 styler
.ColourTo(i
,SCE_NNCRONTAB_STRING
);
80 } else if( ch
== '%') {
81 // signals environment variables
82 state
= SCE_NNCRONTAB_ENVIRONMENT
;
83 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
84 } else if( ch
== '*' ) {
85 // signals an asterisk
86 // no state jump necessary for this simple case...
87 styler
.ColourTo(i
,SCE_NNCRONTAB_ASTERISK
);
88 } else if( isalpha(ch
) || ch
== '<' ) {
89 // signals the start of an identifier
91 buffer
[bufferCount
++] = ch
;
92 state
= SCE_NNCRONTAB_IDENTIFIER
;
93 } else if( isdigit(ch
) ) {
94 // signals the start of a number
96 buffer
[bufferCount
++] = ch
;
97 state
= SCE_NNCRONTAB_NUMBER
;
99 // style it the default style..
100 styler
.ColourTo(i
,SCE_NNCRONTAB_DEFAULT
);
104 case SCE_NNCRONTAB_COMMENT
:
105 // if we find a newline here,
106 // we simply go to default state
107 // else continue to work on it...
108 if( ch
== '\n' || ch
== '\r' ) {
109 state
= SCE_NNCRONTAB_DEFAULT
;
111 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
115 case SCE_NNCRONTAB_TASK
:
116 // if we find a newline here,
117 // we simply go to default state
118 // else continue to work on it...
119 if( ch
== '\n' || ch
== '\r' ) {
120 state
= SCE_NNCRONTAB_DEFAULT
;
122 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
126 case SCE_NNCRONTAB_STRING
:
128 state
= SCE_NNCRONTAB_ENVIRONMENT
;
130 styler
.ColourTo(i
-1,SCE_NNCRONTAB_STRING
);
133 // if we find the end of a string char, we simply go to default state
134 // else we're still dealing with an string...
135 if( (ch
== '"' && styler
.SafeGetCharAt(i
-1)!='\\') ||
136 (ch
== '\n') || (ch
== '\r') ) {
137 state
= SCE_NNCRONTAB_DEFAULT
;
139 styler
.ColourTo(i
,SCE_NNCRONTAB_STRING
);
142 case SCE_NNCRONTAB_ENVIRONMENT
:
143 // if we find the end of a string char, we simply go to default state
144 // else we're still dealing with an string...
145 if( ch
== '%' && insideString
) {
146 state
= SCE_NNCRONTAB_STRING
;
147 insideString
= false;
150 if( (ch
== '%' && styler
.SafeGetCharAt(i
-1)!='\\')
151 || (ch
== '\n') || (ch
== '\r') ) {
152 state
= SCE_NNCRONTAB_DEFAULT
;
153 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
156 styler
.ColourTo(i
+1,SCE_NNCRONTAB_ENVIRONMENT
);
159 case SCE_NNCRONTAB_IDENTIFIER
:
160 // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
161 if( isalnum(ch
) || (ch
== '_') || (ch
== '-') || (ch
== '/') ||
162 (ch
== '$') || (ch
== '.') || (ch
== '<') || (ch
== '>') ) {
163 buffer
[bufferCount
++] = ch
;
165 state
= SCE_NNCRONTAB_DEFAULT
;
166 buffer
[bufferCount
] = '\0';
168 // check if the buffer contains a keyword,
169 // and highlight it if it is a keyword...
170 if(section
.InList(buffer
)) {
171 styler
.ColourTo(i
,SCE_NNCRONTAB_SECTION
);
172 } else if(keyword
.InList(buffer
)) {
173 styler
.ColourTo(i
-1,SCE_NNCRONTAB_KEYWORD
);
174 } // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
175 // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
177 else if(modifier
.InList(buffer
)) {
178 styler
.ColourTo(i
-1,SCE_NNCRONTAB_MODIFIER
);
180 styler
.ColourTo(i
-1,SCE_NNCRONTAB_DEFAULT
);
182 // push back the faulty character
183 chNext
= styler
[i
--];
187 case SCE_NNCRONTAB_NUMBER
:
188 // stay in CONF_NUMBER state until we find a non-numeric
189 if( isdigit(ch
) /* || ch == '.' */ ) {
190 buffer
[bufferCount
++] = ch
;
192 state
= SCE_NNCRONTAB_DEFAULT
;
193 buffer
[bufferCount
] = '\0';
194 // Colourize here... (normal number)
195 styler
.ColourTo(i
-1,SCE_NNCRONTAB_NUMBER
);
196 // push back a character
197 chNext
= styler
[i
--];
204 LexerModule
lmNncrontab(SCLEX_NNCRONTAB
, ColouriseNncrontabDoc
, "nncrontab");