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.eserv.ru/)
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"
25 using namespace Scintilla
;
28 static void ColouriseNncrontabDoc(unsigned int startPos
, int length
, int, WordList
29 *keywordLists
[], Accessor
&styler
)
31 int state
= SCE_NNCRONTAB_DEFAULT
;
32 char chNext
= styler
[startPos
];
33 int lengthDoc
= startPos
+ length
;
34 // create a buffer large enough to take the largest chunk...
35 char *buffer
= new char[length
];
37 // used when highliting environment variables inside quoted string:
38 bool insideString
= false;
40 // this assumes that we have 3 keyword list in conf.properties
41 WordList
§ion
= *keywordLists
[0];
42 WordList
&keyword
= *keywordLists
[1];
43 WordList
&modifier
= *keywordLists
[2];
45 // go through all provided text segment
46 // using the hand-written state machine shown below
47 styler
.StartAt(startPos
);
48 styler
.StartSegment(startPos
);
49 for (int i
= startPos
; i
< lengthDoc
; i
++) {
51 chNext
= styler
.SafeGetCharAt(i
+ 1);
53 if (styler
.IsLeadByte(ch
)) {
54 chNext
= styler
.SafeGetCharAt(i
+ 2);
59 case SCE_NNCRONTAB_DEFAULT
:
60 if( ch
== '\n' || ch
== '\r' || ch
== '\t' || ch
== ' ') {
61 // whitespace is simply ignored here...
62 styler
.ColourTo(i
,SCE_NNCRONTAB_DEFAULT
);
64 } else if( ch
== '#' && styler
.SafeGetCharAt(i
+1) == '(') {
65 // signals the start of a task...
66 state
= SCE_NNCRONTAB_TASK
;
67 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
69 else if( ch
== '\\' && (styler
.SafeGetCharAt(i
+1) == ' ' ||
70 styler
.SafeGetCharAt(i
+1) == '\t')) {
71 // signals the start of an extended comment...
72 state
= SCE_NNCRONTAB_COMMENT
;
73 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
74 } else if( ch
== '#' ) {
75 // signals the start of a plain comment...
76 state
= SCE_NNCRONTAB_COMMENT
;
77 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
78 } else if( ch
== ')' && styler
.SafeGetCharAt(i
+1) == '#') {
79 // signals the end of a task...
80 state
= SCE_NNCRONTAB_TASK
;
81 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
82 } else if( ch
== '"') {
83 state
= SCE_NNCRONTAB_STRING
;
84 styler
.ColourTo(i
,SCE_NNCRONTAB_STRING
);
85 } else if( ch
== '%') {
86 // signals environment variables
87 state
= SCE_NNCRONTAB_ENVIRONMENT
;
88 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
89 } else if( ch
== '<' && styler
.SafeGetCharAt(i
+1) == '%') {
90 // signals environment variables
91 state
= SCE_NNCRONTAB_ENVIRONMENT
;
92 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
93 } else if( ch
== '*' ) {
94 // signals an asterisk
95 // no state jump necessary for this simple case...
96 styler
.ColourTo(i
,SCE_NNCRONTAB_ASTERISK
);
97 } else if( isalpha(ch
) || ch
== '<' ) {
98 // signals the start of an identifier
100 buffer
[bufferCount
++] = ch
;
101 state
= SCE_NNCRONTAB_IDENTIFIER
;
102 } else if( isdigit(ch
) ) {
103 // signals the start of a number
105 buffer
[bufferCount
++] = ch
;
106 state
= SCE_NNCRONTAB_NUMBER
;
108 // style it the default style..
109 styler
.ColourTo(i
,SCE_NNCRONTAB_DEFAULT
);
113 case SCE_NNCRONTAB_COMMENT
:
114 // if we find a newline here,
115 // we simply go to default state
116 // else continue to work on it...
117 if( ch
== '\n' || ch
== '\r' ) {
118 state
= SCE_NNCRONTAB_DEFAULT
;
120 styler
.ColourTo(i
,SCE_NNCRONTAB_COMMENT
);
124 case SCE_NNCRONTAB_TASK
:
125 // if we find a newline here,
126 // we simply go to default state
127 // else continue to work on it...
128 if( ch
== '\n' || ch
== '\r' ) {
129 state
= SCE_NNCRONTAB_DEFAULT
;
131 styler
.ColourTo(i
,SCE_NNCRONTAB_TASK
);
135 case SCE_NNCRONTAB_STRING
:
137 state
= SCE_NNCRONTAB_ENVIRONMENT
;
139 styler
.ColourTo(i
-1,SCE_NNCRONTAB_STRING
);
142 // if we find the end of a string char, we simply go to default state
143 // else we're still dealing with an string...
144 if( (ch
== '"' && styler
.SafeGetCharAt(i
-1)!='\\') ||
145 (ch
== '\n') || (ch
== '\r') ) {
146 state
= SCE_NNCRONTAB_DEFAULT
;
148 styler
.ColourTo(i
,SCE_NNCRONTAB_STRING
);
151 case SCE_NNCRONTAB_ENVIRONMENT
:
152 // if we find the end of a string char, we simply go to default state
153 // else we're still dealing with an string...
154 if( ch
== '%' && insideString
) {
155 state
= SCE_NNCRONTAB_STRING
;
156 insideString
= false;
159 if( (ch
== '%' && styler
.SafeGetCharAt(i
-1)!='\\')
160 || (ch
== '\n') || (ch
== '\r') || (ch
== '>') ) {
161 state
= SCE_NNCRONTAB_DEFAULT
;
162 styler
.ColourTo(i
,SCE_NNCRONTAB_ENVIRONMENT
);
165 styler
.ColourTo(i
+1,SCE_NNCRONTAB_ENVIRONMENT
);
168 case SCE_NNCRONTAB_IDENTIFIER
:
169 // stay in CONF_IDENTIFIER state until we find a non-alphanumeric
170 if( isalnum(ch
) || (ch
== '_') || (ch
== '-') || (ch
== '/') ||
171 (ch
== '$') || (ch
== '.') || (ch
== '<') || (ch
== '>') ||
173 buffer
[bufferCount
++] = ch
;
175 state
= SCE_NNCRONTAB_DEFAULT
;
176 buffer
[bufferCount
] = '\0';
178 // check if the buffer contains a keyword,
179 // and highlight it if it is a keyword...
180 if(section
.InList(buffer
)) {
181 styler
.ColourTo(i
,SCE_NNCRONTAB_SECTION
);
182 } else if(keyword
.InList(buffer
)) {
183 styler
.ColourTo(i
-1,SCE_NNCRONTAB_KEYWORD
);
184 } // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
185 // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
187 else if(modifier
.InList(buffer
)) {
188 styler
.ColourTo(i
-1,SCE_NNCRONTAB_MODIFIER
);
190 styler
.ColourTo(i
-1,SCE_NNCRONTAB_DEFAULT
);
192 // push back the faulty character
193 chNext
= styler
[i
--];
197 case SCE_NNCRONTAB_NUMBER
:
198 // stay in CONF_NUMBER state until we find a non-numeric
199 if( isdigit(ch
) /* || ch == '.' */ ) {
200 buffer
[bufferCount
++] = ch
;
202 state
= SCE_NNCRONTAB_DEFAULT
;
203 buffer
[bufferCount
] = '\0';
204 // Colourize here... (normal number)
205 styler
.ColourTo(i
-1,SCE_NNCRONTAB_NUMBER
);
206 // push back a character
207 chNext
= styler
[i
--];
215 static const char * const cronWordListDesc
[] = {
216 "Section keywords and Forth words",
217 "nnCrontab keywords",
222 LexerModule
lmNncrontab(SCLEX_NNCRONTAB
, ColouriseNncrontabDoc
, "nncrontab", 0, cronWordListDesc
);