2 /******************************************************************************
4 * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org) *
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. *
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. *
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 ******************************************************************************/
21 #include "config/configcompiler.h"
22 #include "config/expression.h"
23 #include "config/typerule.h"
24 #include "config/configcompilercontext.h"
26 using namespace icinga;
28 #include "config/config_parser.hh"
31 #define YYLTYPE icinga::DebugInfo
33 #define YY_EXTRA_TYPE ConfigCompiler *
34 #define YY_USER_ACTION \
36 yylloc->Path = yyextra->GetPath(); \
37 yylloc->FirstLine = yylineno; \
38 yylloc->FirstColumn = yycolumn; \
39 yylloc->LastLine = yylineno; \
40 yylloc->LastColumn = yycolumn + yyleng - 1; \
44 #define YY_INPUT(buf, result, max_size) \
46 result = yyextra->ReadInput(buf, max_size); \
54 static void lb_init(lex_buf *lb)
60 static void lb_cleanup(lex_buf *lb)
65 static void lb_append_char(lex_buf *lb, char new_char)
67 const size_t block_size = 64;
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;
72 if (old_blocks != new_blocks) {
73 char *new_buf = (char *)realloc(lb->buf, new_blocks * block_size);
75 if (new_buf == NULL && new_blocks > 0)
76 throw std::bad_alloc();
82 lb->buf[lb->size - 1] = new_char;
85 static char *lb_steal(lex_buf *lb)
87 lb_append_char(lb, '\0');
96 %option reentrant noyywrap yylineno
97 %option bison-bridge bison-locations
98 %option never-interactive nounistd
107 \" { lb_init(&string_buf); BEGIN(STRING); }
112 lb_append_char(&string_buf, '\0');
114 yylval->text = lb_steal(&string_buf);
120 std::ostringstream msgbuf;
121 msgbuf << "Unterminated string found: " << *yylloc;
122 ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
126 <STRING>\\[0-7]{1,3} {
127 /* octal escape sequence */
130 (void) sscanf(yytext + 1, "%o", &result);
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());
139 lb_append_char(&string_buf, result);
143 /* generate error - bad escape sequence; something
144 * like '\48' or '\0777777'
146 std::ostringstream msgbuf;
147 msgbuf << "Bad escape sequence found: " << yytext << " " << *yylloc;
148 ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
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]); }
162 lb_append_char(&string_buf, *yptr++);
165 \{\{\{ { lb_init(&string_buf); BEGIN(HEREDOC); }
170 lb_append_char(&string_buf, '\0');
172 yylval->text = lb_steal(&string_buf);
177 <HEREDOC>(.|\n) { lb_append_char(&string_buf, yytext[0]); }
180 "/*" BEGIN(C_COMMENT);
185 [^*] /* ignore comment */
186 "*" /* ignore star */
190 std::ostringstream msgbuf;
191 msgbuf << "End-of-file while in comment: " << yytext << " " << *yylloc;
192 ConfigCompilerContext::GetInstance()->AddMessage(true, msgbuf.str());
197 \/\/[^\n]* /* ignore C++-style comments */
198 [ \t\r\n] /* ignore whitespace */
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;
219 partial return T_PARTIAL;
220 true { yylval->num = 1; return T_NUMBER; }
221 false { yylval->num = 0; return T_NUMBER; }
224 const return T_CONST;
225 apply return T_APPLY;
227 where return T_WHERE;
228 \<\< return T_SHIFT_LEFT;
229 \>\> return T_SHIFT_RIGHT;
231 != return T_NOT_EQUAL;
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; }
255 void ConfigCompiler::InitializeScanner(void)
257 yylex_init(&m_Scanner);
258 yyset_extra(this, m_Scanner);
261 void ConfigCompiler::DestroyScanner(void)
263 yylex_destroy(m_Scanner);