]>
Commit | Line | Data |
---|---|---|
b8b0e402 RD |
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. | |
a834585d | 5 | ** (http://nemtsev.eserv.ru/) |
b8b0e402 RD |
6 | **/ |
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. | |
9 | ||
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
12 | #include <ctype.h> | |
13 | #include <stdio.h> | |
14 | #include <stdarg.h> | |
15 | ||
16 | #include "Platform.h" | |
17 | ||
18 | #include "PropSet.h" | |
19 | #include "Accessor.h" | |
20 | #include "KeyWords.h" | |
21 | #include "Scintilla.h" | |
22 | #include "SciLexer.h" | |
23 | ||
24 | static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList | |
25 | *keywordLists[], Accessor &styler) | |
26 | { | |
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]; | |
32 | int bufferCount = 0; | |
33 | // used when highliting environment variables inside quoted string: | |
34 | bool insideString = false; | |
35 | ||
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]; | |
40 | ||
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++) { | |
46 | char ch = chNext; | |
47 | chNext = styler.SafeGetCharAt(i + 1); | |
48 | ||
49 | if (styler.IsLeadByte(ch)) { | |
50 | chNext = styler.SafeGetCharAt(i + 2); | |
51 | i++; | |
52 | continue; | |
53 | } | |
54 | switch(state) { | |
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); | |
59 | break; | |
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); | |
64 | } | |
9e730a78 | 65 | else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' || |
a834585d | 66 | styler.SafeGetCharAt(i+1) == '\t')) { |
b8b0e402 RD |
67 | // signals the start of an extended comment... |
68 | state = SCE_NNCRONTAB_COMMENT; | |
69 | styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); | |
70 | } else if( ch == '#' ) { | |
71 | // signals the start of a plain comment... | |
72 | state = SCE_NNCRONTAB_COMMENT; | |
73 | styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); | |
74 | } else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') { | |
75 | // signals the end of a task... | |
76 | state = SCE_NNCRONTAB_TASK; | |
77 | styler.ColourTo(i,SCE_NNCRONTAB_TASK); | |
78 | } else if( ch == '"') { | |
79 | state = SCE_NNCRONTAB_STRING; | |
80 | styler.ColourTo(i,SCE_NNCRONTAB_STRING); | |
81 | } else if( ch == '%') { | |
82 | // signals environment variables | |
83 | state = SCE_NNCRONTAB_ENVIRONMENT; | |
84 | styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); | |
a834585d RD |
85 | } else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') { |
86 | // signals environment variables | |
87 | state = SCE_NNCRONTAB_ENVIRONMENT; | |
88 | styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); | |
b8b0e402 RD |
89 | } else if( ch == '*' ) { |
90 | // signals an asterisk | |
91 | // no state jump necessary for this simple case... | |
92 | styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); | |
93 | } else if( isalpha(ch) || ch == '<' ) { | |
94 | // signals the start of an identifier | |
95 | bufferCount = 0; | |
96 | buffer[bufferCount++] = ch; | |
97 | state = SCE_NNCRONTAB_IDENTIFIER; | |
98 | } else if( isdigit(ch) ) { | |
99 | // signals the start of a number | |
100 | bufferCount = 0; | |
101 | buffer[bufferCount++] = ch; | |
102 | state = SCE_NNCRONTAB_NUMBER; | |
103 | } else { | |
104 | // style it the default style.. | |
105 | styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT); | |
106 | } | |
107 | break; | |
108 | ||
109 | case SCE_NNCRONTAB_COMMENT: | |
110 | // if we find a newline here, | |
111 | // we simply go to default state | |
112 | // else continue to work on it... | |
113 | if( ch == '\n' || ch == '\r' ) { | |
114 | state = SCE_NNCRONTAB_DEFAULT; | |
115 | } else { | |
116 | styler.ColourTo(i,SCE_NNCRONTAB_COMMENT); | |
117 | } | |
118 | break; | |
119 | ||
120 | case SCE_NNCRONTAB_TASK: | |
121 | // if we find a newline here, | |
122 | // we simply go to default state | |
123 | // else continue to work on it... | |
124 | if( ch == '\n' || ch == '\r' ) { | |
125 | state = SCE_NNCRONTAB_DEFAULT; | |
126 | } else { | |
127 | styler.ColourTo(i,SCE_NNCRONTAB_TASK); | |
128 | } | |
129 | break; | |
130 | ||
131 | case SCE_NNCRONTAB_STRING: | |
132 | if( ch == '%' ) { | |
133 | state = SCE_NNCRONTAB_ENVIRONMENT; | |
134 | insideString = true; | |
135 | styler.ColourTo(i-1,SCE_NNCRONTAB_STRING); | |
136 | break; | |
137 | } | |
138 | // if we find the end of a string char, we simply go to default state | |
139 | // else we're still dealing with an string... | |
140 | if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || | |
141 | (ch == '\n') || (ch == '\r') ) { | |
142 | state = SCE_NNCRONTAB_DEFAULT; | |
143 | } | |
144 | styler.ColourTo(i,SCE_NNCRONTAB_STRING); | |
145 | break; | |
146 | ||
147 | case SCE_NNCRONTAB_ENVIRONMENT: | |
148 | // if we find the end of a string char, we simply go to default state | |
149 | // else we're still dealing with an string... | |
150 | if( ch == '%' && insideString ) { | |
151 | state = SCE_NNCRONTAB_STRING; | |
152 | insideString = false; | |
153 | break; | |
154 | } | |
155 | if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\') | |
a834585d | 156 | || (ch == '\n') || (ch == '\r') || (ch == '>') ) { |
b8b0e402 RD |
157 | state = SCE_NNCRONTAB_DEFAULT; |
158 | styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT); | |
159 | break; | |
160 | } | |
161 | styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT); | |
162 | break; | |
163 | ||
164 | case SCE_NNCRONTAB_IDENTIFIER: | |
165 | // stay in CONF_IDENTIFIER state until we find a non-alphanumeric | |
166 | if( isalnum(ch) || (ch == '_') || (ch == '-') || (ch == '/') || | |
a834585d RD |
167 | (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || |
168 | (ch == '@') ) { | |
b8b0e402 RD |
169 | buffer[bufferCount++] = ch; |
170 | } else { | |
171 | state = SCE_NNCRONTAB_DEFAULT; | |
172 | buffer[bufferCount] = '\0'; | |
173 | ||
174 | // check if the buffer contains a keyword, | |
175 | // and highlight it if it is a keyword... | |
176 | if(section.InList(buffer)) { | |
177 | styler.ColourTo(i,SCE_NNCRONTAB_SECTION ); | |
178 | } else if(keyword.InList(buffer)) { | |
179 | styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD ); | |
180 | } // else if(strchr(buffer,'/') || strchr(buffer,'.')) { | |
181 | // styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION); | |
182 | // } | |
183 | else if(modifier.InList(buffer)) { | |
184 | styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER ); | |
185 | } else { | |
186 | styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT); | |
187 | } | |
188 | // push back the faulty character | |
189 | chNext = styler[i--]; | |
190 | } | |
191 | break; | |
192 | ||
193 | case SCE_NNCRONTAB_NUMBER: | |
194 | // stay in CONF_NUMBER state until we find a non-numeric | |
195 | if( isdigit(ch) /* || ch == '.' */ ) { | |
196 | buffer[bufferCount++] = ch; | |
197 | } else { | |
198 | state = SCE_NNCRONTAB_DEFAULT; | |
199 | buffer[bufferCount] = '\0'; | |
200 | // Colourize here... (normal number) | |
201 | styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER); | |
202 | // push back a character | |
203 | chNext = styler[i--]; | |
204 | } | |
205 | break; | |
206 | } | |
207 | } | |
1a2fb4cd | 208 | delete []buffer; |
b8b0e402 RD |
209 | } |
210 | ||
9e730a78 RD |
211 | static const char * const cronWordListDesc[] = { |
212 | "Section keywords and Forth words", | |
213 | "nnCrontab keywords", | |
214 | "Modifiers", | |
215 | 0 | |
216 | }; | |
217 | ||
218 | LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc); |