]> granicus.if.org Git - icinga2/blob - lib/config/config_lexer.ll
Merge branch 'feature/apply-5789' into next
[icinga2] / lib / config / config_lexer.ll
1 %{
2 /******************************************************************************
3  * Icinga 2                                                                   *
4  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
5  *                                                                            *
6  * This program is free software; you can redistribute it and/or              *
7  * modify it under the terms of the GNU General Public License                *
8  * as published by the Free Software Foundation; either version 2             *
9  * of the License, or (at your option) any later version.                     *
10  *                                                                            *
11  * This program is distributed in the hope that it will be useful,            *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
14  * GNU General Public License for more details.                               *
15  *                                                                            *
16  * You should have received a copy of the GNU General Public License          *
17  * along with this program; if not, write to the Free Software Foundation     *
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
19  ******************************************************************************/
20
21 #include "config/configcompiler.h"
22 #include "config/expression.h"
23 #include "config/typerule.h"
24 #include "config/configcompilercontext.h"
25
26 using namespace icinga;
27
28 #include "config/config_parser.hh"
29 #include <sstream>
30
31 #define YYLTYPE icinga::DebugInfo
32
33 #define YY_EXTRA_TYPE ConfigCompiler *
34 #define YY_USER_ACTION                                  \
35 do {                                                    \
36         yylloc->Path = yyextra->GetPath();              \
37         yylloc->FirstLine = yylineno;                   \
38         yylloc->FirstColumn = yycolumn;                 \
39         yylloc->LastLine = yylineno;                    \
40         yylloc->LastColumn = yycolumn + yyleng - 1;     \
41         yycolumn += yyleng;                             \
42 } while (0);
43
44 #define YY_INPUT(buf, result, max_size)                 \
45 do {                                                    \
46         result = yyextra->ReadInput(buf, max_size);     \
47 } while (0)
48
49 struct lex_buf {
50         char *buf;
51         size_t size;
52 };
53
54 static void lb_init(lex_buf *lb)
55 {
56         lb->buf = NULL;
57         lb->size = 0;
58 }
59
60 static void lb_cleanup(lex_buf *lb)
61 {
62         free(lb->buf);
63 }
64
65 static void lb_append_char(lex_buf *lb, char new_char)
66 {
67         const size_t block_size = 64;
68
69         size_t old_blocks = (lb->size + (block_size - 1)) / block_size;
70         size_t new_blocks = ((lb->size + 1) + (block_size - 1)) / block_size;
71
72         if (old_blocks != new_blocks) {
73                 char *new_buf = (char *)realloc(lb->buf, new_blocks * block_size);
74
75                 if (new_buf == NULL && new_blocks > 0)
76                         throw std::bad_alloc();
77
78                 lb->buf = new_buf;
79         }
80
81         lb->size++;
82         lb->buf[lb->size - 1] = new_char;
83 }
84
85 static char *lb_steal(lex_buf *lb)
86 {
87         lb_append_char(lb, '\0');
88
89         char *buf = lb->buf;
90         lb->buf = NULL;
91         lb->size = 0;
92         return buf;
93 }
94 %}
95
96 %option reentrant noyywrap yylineno
97 %option bison-bridge bison-locations
98 %option never-interactive nounistd
99
100 %x C_COMMENT
101 %x STRING
102 %x HEREDOC
103
104 %%
105         lex_buf string_buf;
106
107 \"                              { lb_init(&string_buf); BEGIN(STRING); }
108
109 <STRING>\"                      {
110         BEGIN(INITIAL);
111
112         lb_append_char(&string_buf, '\0');
113
114         yylval->text = lb_steal(&string_buf);
115
116         return T_STRING;
117                                 }
118
119 <STRING>\n                      {
120         std::ostringstream msgbuf;
121         msgbuf << "Unterminated string found: " << *yylloc;
122         ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
123         BEGIN(INITIAL);
124                                 }
125
126 <STRING>\\[0-7]{1,3}            {
127         /* octal escape sequence */
128         int result;
129
130         (void) sscanf(yytext + 1, "%o", &result);
131
132         if (result > 0xff) {
133                 /* error, constant is out-of-bounds */
134                 std::ostringstream msgbuf;
135                 msgbuf << "Constant is out-of-bounds: " << yytext << " " << *yylloc;
136                 ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
137         }
138
139         lb_append_char(&string_buf, result);
140                                 }
141
142 <STRING>\\[0-9]+                {
143         /* generate error - bad escape sequence; something
144          * like '\48' or '\0777777'
145          */
146         std::ostringstream msgbuf;
147         msgbuf << "Bad escape sequence found: " << yytext << " " << *yylloc;
148         ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
149                                 }
150
151 <STRING>\\n                     { lb_append_char(&string_buf, '\n'); }
152 <STRING>\\t                     { lb_append_char(&string_buf, '\t'); }
153 <STRING>\\r                     { lb_append_char(&string_buf, '\r'); }
154 <STRING>\\b                     { lb_append_char(&string_buf, '\b'); }
155 <STRING>\\f                     { lb_append_char(&string_buf, '\f'); }
156 <STRING>\\(.|\n)                { lb_append_char(&string_buf, yytext[1]); }
157
158 <STRING>[^\\\n\"]+              {
159         char *yptr = yytext;
160
161         while (*yptr)
162                 lb_append_char(&string_buf, *yptr++);
163                                }
164
165 \{\{\{                          { lb_init(&string_buf); BEGIN(HEREDOC); }
166
167 <HEREDOC>\}\}\}                 {
168         BEGIN(INITIAL);
169
170         lb_append_char(&string_buf, '\0');
171
172         yylval->text = lb_steal(&string_buf);
173
174         return T_STRING;
175                                 }
176
177 <HEREDOC>(.|\n)                 { lb_append_char(&string_buf, yytext[0]); }
178
179 <INITIAL>{
180 "/*"                            BEGIN(C_COMMENT);
181 }
182
183 <C_COMMENT>{
184 "*/"                            BEGIN(INITIAL);
185 [^*]                            /* ignore comment */
186 "*"                             /* ignore star */
187 }
188
189 <C_COMMENT><<EOF>>              {
190                 std::ostringstream msgbuf;
191                 msgbuf << "End-of-file while in comment: " << yytext << " " << *yylloc;
192                 ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
193                 yyterminate();
194                                 }
195
196
197 \/\/[^\n]*                      /* ignore C++-style comments */
198 [ \t\r\n]                       /* ignore whitespace */
199
200 <INITIAL>{
201 type                            return T_TYPE;
202 dictionary                      { yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; }
203 array                           { yylval->type = TypeArray; return T_TYPE_ARRAY; }
204 number                          { yylval->type = TypeNumber; return T_TYPE_NUMBER; }
205 string                          { yylval->type = TypeString; return T_TYPE_STRING; }
206 scalar                          { yylval->type = TypeScalar; return T_TYPE_SCALAR; }
207 any                             { yylval->type = TypeAny; return T_TYPE_ANY; }
208 name                            { yylval->type = TypeName; return T_TYPE_NAME; }
209 %validator                      { return T_VALIDATOR; }
210 %require                        { return T_REQUIRE; }
211 %attribute                      { return T_ATTRIBUTE; }
212 object                          return T_OBJECT;
213 template                        return T_TEMPLATE;
214 include                         return T_INCLUDE;
215 include_recursive               return T_INCLUDE_RECURSIVE;
216 library                         return T_LIBRARY;
217 inherits                        return T_INHERITS;
218 null                            return T_NULL;
219 partial                         return T_PARTIAL;
220 true                            { yylval->num = 1; return T_NUMBER; }
221 false                           { yylval->num = 0; return T_NUMBER; }
222 set                             return T_VAR;
223 var                             return T_VAR;
224 const                           return T_CONST;
225 apply                           return T_APPLY;
226 to                              return T_TO;
227 where                           return T_WHERE;
228 \<\<                            return T_SHIFT_LEFT;
229 \>\>                            return T_SHIFT_RIGHT;
230 ==                              return T_EQUAL;
231 !=                              return T_NOT_EQUAL;
232 !in                             return T_NOT_IN;
233 in                              return T_IN;
234 &&                              return T_LOGICAL_AND;
235 \|\|                            return T_LOGICAL_OR;
236 [a-zA-Z_][:a-zA-Z0-9\-_]*       { yylval->text = strdup(yytext); return T_IDENTIFIER; }
237 \<[^\>]*\>                      { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; }
238 -?[0-9]+(\.[0-9]+)?ms           { yylval->num = strtod(yytext, NULL) / 1000; return T_NUMBER; }
239 -?[0-9]+(\.[0-9]+)?d            { yylval->num = strtod(yytext, NULL) * 60 * 60 * 24; return T_NUMBER; }
240 -?[0-9]+(\.[0-9]+)?h            { yylval->num = strtod(yytext, NULL) * 60 * 60; return T_NUMBER; }
241 -?[0-9]+(\.[0-9]+)?m            { yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; }
242 -?[0-9]+(\.[0-9]+)?s            { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
243 -?[0-9]+(\.[0-9]+)?             { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
244 =                               { yylval->op = OperatorSet; return T_SET; }
245 \+=                             { yylval->op = OperatorPlus; return T_PLUS_EQUAL; }
246 -=                              { yylval->op = OperatorMinus; return T_MINUS_EQUAL; }
247 \*=                             { yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; }
248 \/=                             { yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; }
249 }
250
251 .                               return yytext[0];
252
253 %%
254
255 void ConfigCompiler::InitializeScanner(void)
256 {
257         yylex_init(&m_Scanner);
258         yyset_extra(this, m_Scanner);
259 }
260
261 void ConfigCompiler::DestroyScanner(void)
262 {
263         yylex_destroy(m_Scanner);
264 }