Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
ac00ace4
Commit
ac00ace4
authored
Nov 14, 2015
by
Francis Dupont
Browse files
[4088] Merged trac4088fd private branch
parents
11bc4b3c
81ab4ec7
Changes
18
Hide whitespace changes
Inline
Side-by-side
src/lib/eval/Makefile.am
View file @
ac00ace4
...
...
@@ -17,7 +17,7 @@ libkea_eval_la_SOURCES += token.cc token.h
libkea_eval_la_SOURCES
+=
parser.cc parser.h
libkea_eval_la_SOURCES
+=
lexer.cc
libkea_eval_la_SOURCES
+=
eval_context.cc
libkea_eval_la_SOURCES
+=
eval_context.cc
eval_context.h eval_context_decl.h
nodist_libkea_eval_la_SOURCES
=
eval_messages.h eval_messages.cc
...
...
src/lib/eval/eval.dox
View file @
ac00ace4
...
...
@@ -22,9 +22,8 @@
classification, but in the future may be also used for other applications.
The external interface to the library is the @ref isc::eval::EvalContext
class. Once instantiated, it offers two major methods:
@ref isc::eval::EvalContext::parseFile which parses the content of a file
and @ref isc::eval::EvalContext::parseString, which parses the specified
class. Once instantiated, it offers a major method:
@ref isc::eval::EvalContext::parseString, which parses the specified
string. Once the expression is parsed, it is converted to a collection of
tokens that are stored in Reverse Polish Notation in
EvalContext::expression.
...
...
@@ -66,27 +65,35 @@
@code
01. %start expression;
02.
03. expression
:
04.
token EQUAL
token
05.
| token
;
03. expression
: token EQUAL token
04.
|
token
05.
;
06.
07. token:
08. STRING {
09. TokenPtr str(new TokenString($1));
10. ctx.expression.push_back(str);
11.}
12.| OPTION {
13. TokenPtr opt(new TokenOption($1));
14. ctx.expression.push_back(opt);
15.};
07. token : STRING
08. {
09. TokenPtr str(new TokenString($1));
10. ctx.expression.push_back(str);
11. }
12. | HEXSTRING
13. {
14. TokenPtr hex(new TokenHexString($1));
15. ctx.expression.push_back(hex);
16. }
17. | OPTION '[' INTEGER ']'
18. {
19. TokenPtr opt(new TokenOption($3));
20. ctx.expression.push_back(opt);
21. }
22. ;
@endcode
This code determines that the grammar starts from expression (line 1).
The actual definition of expression (lines 3-5) may either be a
single token or an expression "token == token" (EQUAL has been defined as
"==" elsewhere). Token is further
defined in lines 7-15: it may either be a string (lines 8-11) or option
(lines 12-15). When the actual case is determined, the respective C++ action
defined in lines 7-22: it may either be a string (lines 7-11),
a hex string (lines 12-16) or option (lines 17-21).
When the actual case is determined, the respective C++ action
is executed. For example, if the token is a string, the TokenString class is
instantiated with the appropriate value and put onto the expression vector.
...
...
src/lib/eval/eval_context.cc
View file @
ac00ace4
...
...
@@ -26,46 +26,27 @@ EvalContext::~EvalContext()
{
}
int
EvalContext
::
parse
File
(
const
std
::
string
&
filename
)
bool
EvalContext
::
parse
String
(
const
std
::
string
&
str
)
{
file
=
filename
;
scanBegin
();
file_
=
"<string>"
;
string_
=
str
;
scanStringBegin
();
isc
::
eval
::
EvalParser
parser
(
*
this
);
parser
.
set_debug_level
(
trace_parsing_
);
int
res
=
parser
.
parse
();
scanEnd
();
return
res
;
}
int
EvalContext
::
parseString
(
const
std
::
string
&
str
)
{
/// @todo: Is there any way for the parser to read from a stream,
/// rather than a file? It would be better to use stringstream,
/// but it seems that the lexer operates on FILE* interface.
// Put the content into a file and then open that file for reading.
remove
(
"/tmp/eval"
);
std
::
fstream
f
(
"/tmp/eval"
,
std
::
ios
::
out
);
if
(
!
f
.
good
())
{
isc_throw
(
isc
::
Unexpected
,
"Can't write /tmp/eval file"
);
}
f
<<
str
;
f
.
close
();
return
(
parseFile
(
"/tmp/eval"
));
scanStringEnd
();
return
(
res
==
0
);
}
void
EvalContext
::
error
(
const
isc
::
eval
::
location
&
l
,
const
std
::
string
&
m
)
EvalContext
::
error
(
const
isc
::
eval
::
location
&
l
oc
,
const
std
::
string
&
what
)
{
isc_throw
(
EvalError
,
l
<<
": "
<<
m
);
isc_throw
(
Eval
Parse
Error
,
l
oc
<<
": "
<<
what
);
}
void
EvalContext
::
error
(
const
std
::
string
&
m
)
EvalContext
::
error
(
const
std
::
string
&
what
)
{
isc_throw
(
EvalError
,
m
);
isc_throw
(
Eval
Parse
Error
,
what
);
}
src/lib/eval/eval_context.h
View file @
ac00ace4
...
...
@@ -17,6 +17,7 @@
#include
<string>
#include
<map>
#include
<eval/parser.h>
#include
<eval/eval_context_decl.h>
#include
<exceptions/exceptions.h>
// Tell Flex the lexer's prototype ...
...
...
@@ -25,10 +26,13 @@
// ... and declare it for the parser's sake.
YY_DECL
;
namespace
isc
{
namespace
eval
{
/// @brief Evaluation error exception raised when trying to parse an axceptions.
class
EvalError
:
public
isc
::
Exception
{
class
Eval
Parse
Error
:
public
isc
::
Exception
{
public:
EvalError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
Eval
Parse
Error
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{
};
};
...
...
@@ -46,32 +50,30 @@ public:
/// @brief Parsed expression (output tokens are stored here)
isc
::
dhcp
::
Expression
expression
;
/// @brief Method called before scanning starts.
void
scanBegin
();
/// @brief Method called before scanning starts
on a string
.
void
scan
String
Begin
();
/// @brief Method called after the last tokens are scanned.
void
scanEnd
();
/// @brief Method called after the last tokens are scanned
from a string
.
void
scan
String
End
();
/// @brief Runs the parser on specified file.
///
/// @param filename
/// Return 0 on success.
int
parseFile
(
const
std
::
string
&
filename
);
/// @brief Run the parser on the string specified.
///
/// @param str string to be written
int
parseString
(
const
std
::
string
&
str
);
/// @return true on success.
bool
parseString
(
const
std
::
string
&
str
);
/// @brief The name of the file being parsed.
/// Used later to pass the file name to the location tracker.
std
::
string
file
;
std
::
string
file_
;
/// @brief The string being parsed.
std
::
string
string_
;
/// @brief Error handler
///
/// @param l location within the parsed file when experienced a problem.
/// @param l
oc
location within the parsed file when experienced a problem.
/// @param what string explaining the nature of the error.
void
error
(
const
isc
::
eval
::
location
&
l
,
const
std
::
string
&
what
);
void
error
(
const
isc
::
eval
::
location
&
l
oc
,
const
std
::
string
&
what
);
/// @brief Error handler
///
...
...
@@ -87,4 +89,8 @@ public:
bool
trace_parsing_
;
};
#endif // ! EVALCONTEXT_H
};
// end of isc::eval namespace
};
// end of isc namespace
#endif
src/lib/eval/eval_context_decl.h
0 → 100644
View file @
ac00ace4
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef EVAL_CONTEXT_DECL_H
#define EVAL_CONTEXT_DECL_H
/// @file eval_context_decl.h Forward declaration of the EvalContext class
namespace
isc
{
namespace
eval
{
class
EvalContext
;
};
// end of isc::eval namespace
};
// end of isc namespace
#endif
src/lib/eval/eval_messages.mes
View file @
ac00ace4
...
...
@@ -18,8 +18,3 @@ $NAMESPACE isc::dhcp
This debug message indicates that the expression has been evaluated
to said value. This message is mostly useful during debugging of the
client classification expressions.
% EVAL_SUBSTRING_BAD_PARAM_CONVERSION starting %1, length %2
This debug message indicates that the parameter for the starting postion
or length of the substring couldn't be converted to an integer. In this
case the substring routine returns an empty string.
src/lib/eval/lexer.cc
View file @
ac00ace4
...
...
@@ -18,7 +18,7 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 3
7
#define YY_FLEX_SUBMINOR_VERSION 3
9
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
...
...
@@ -230,6 +230,13 @@ extern FILE *yyin, *yyout;
if ( yytext[yyl] == '\n' )\
--yylineno;\
}while(0)
#define YY_LINENO_REWIND_TO(dst) \
do {\
const char *p;\
for ( p = yy_cp-1; p >= (dst); --p)\
if ( *p == '\n' )\
--yylineno;\
}while(0)
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
...
...
@@ -438,6 +445,8 @@ int yylineno = 1;
extern
char
*
yytext
;
#define yytext_ptr yytext
/* %% [1.5] DFA */
/* %if-c-only Standard (non-C++) definition */
static
yy_state_type
yy_get_previous_state
(
void
);
...
...
@@ -460,8 +469,8 @@ static void yy_fatal_error (yyconst char msg[] );
(yy_c_buf_p) = yy_cp;
/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
#define YY_NUM_RULES 1
1
#define YY_END_OF_BUFFER 1
2
#define YY_NUM_RULES 1
6
#define YY_END_OF_BUFFER 1
7
/* This struct is not used in this scanner,
but its presence is necessary. */
struct
yy_trans_info
...
...
@@ -469,12 +478,13 @@ struct yy_trans_info
flex_int32_t
yy_verify
;
flex_int32_t
yy_nxt
;
};
static
yyconst
flex_int16_t
yy_accept
[
36
]
=
static
yyconst
flex_int16_t
yy_accept
[
44
]
=
{
0
,
0
,
0
,
12
,
10
,
1
,
2
,
10
,
7
,
8
,
9
,
10
,
10
,
10
,
1
,
2
,
3
,
0
,
5
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
4
,
6
,
0
0
,
0
,
17
,
15
,
1
,
2
,
15
,
10
,
11
,
14
,
15
,
5
,
5
,
15
,
12
,
13
,
15
,
15
,
15
,
1
,
2
,
0
,
3
,
5
,
0
,
6
,
0
,
0
,
0
,
4
,
9
,
0
,
0
,
0
,
0
,
0
,
0
,
7
,
0
,
0
,
0
,
8
,
0
}
;
static
yyconst
flex_int32_t
yy_ec
[
256
]
=
...
...
@@ -483,16 +493,16 @@ static yyconst flex_int32_t yy_ec[256] =
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
2
,
1
,
1
,
1
,
1
,
1
,
1
,
4
,
5
,
6
,
1
,
1
,
7
,
1
,
1
,
1
,
8
,
8
,
8
,
8
,
8
,
8
,
8
,
8
,
8
,
8
,
1
,
1
,
1
,
9
,
1
,
1
,
1
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
10
,
1
0
,
1
0
,
1
0
,
1
0
,
10
,
1
0
,
1
0
,
1
0
,
1
0
,
10
,
1
0
,
1
0
,
1
0
,
1
0
,
10
,
1
0
,
1
0
,
1
0
,
1
0
,
1
1
,
1
,
1
2
,
1
,
1
0
,
1
,
1
0
,
1
3
,
1
0
,
1
0
,
1
0
,
1
0
,
1
4
,
1
0
,
1
5
,
10
,
1
0
,
1
0
,
1
0
,
1
6
,
17
,
18
,
1
0
,
19
,
2
0
,
2
1
,
2
2
,
10
,
1
0
,
1
0
,
10
,
1
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
6
,
1
,
1
,
7
,
8
,
1
,
1
,
9
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
10
,
1
,
1
,
1
,
11
,
1
,
1
,
1
,
1
2
,
1
2
,
1
2
,
1
2
,
1
2
,
1
2
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
3
,
1
,
1
,
1
4
,
1
,
1
5
,
1
,
1
,
1
,
1
6
,
1
7
,
1
2
,
1
2
,
1
2
,
1
2
,
1
8
,
1
,
1
9
,
1
,
1
,
2
0
,
1
,
2
1
,
22
,
23
,
1
,
24
,
2
5
,
2
6
,
2
7
,
1
,
1
,
1
3
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
...
...
@@ -509,57 +519,61 @@ static yyconst flex_int32_t yy_ec[256] =
1
,
1
,
1
,
1
,
1
}
;
static
yyconst
flex_int32_t
yy_meta
[
2
3
]
=
static
yyconst
flex_int32_t
yy_meta
[
2
8
]
=
{
0
,
1
,
1
,
1
,
2
,
1
,
1
,
1
,
2
,
1
,
2
,
1
,
1
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
,
2
1
,
1
,
2
,
1
,
1
,
1
,
1
,
1
,
3
,
3
,
1
,
3
,
1
,
1
,
1
,
3
,
3
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
}
;
static
yyconst
flex_int16_t
yy_base
[
37
]
=
static
yyconst
flex_int16_t
yy_base
[
46
]
=
{
0
,
0
,
0
,
48
,
49
,
45
,
43
,
41
,
49
,
49
,
49
,
35
,
25
,
20
,
39
,
37
,
49
,
35
,
49
,
17
,
24
,
21
,
15
,
17
,
12
,
16
,
12
,
19
,
14
,
20
,
10
,
15
,
11
,
49
,
49
,
49
,
22
0
,
0
,
62
,
63
,
59
,
57
,
55
,
63
,
63
,
63
,
19
,
21
,
23
,
47
,
63
,
63
,
37
,
33
,
28
,
52
,
50
,
48
,
63
,
26
,
0
,
63
,
31
,
24
,
32
,
0
,
63
,
29
,
22
,
24
,
19
,
23
,
19
,
63
,
23
,
20
,
22
,
63
,
63
,
36
,
35
}
;
static
yyconst
flex_int16_t
yy_def
[
37
]
=
static
yyconst
flex_int16_t
yy_def
[
46
]
=
{
0
,
35
,
1
,
35
,
35
,
35
,
35
,
36
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
36
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
0
,
35
43
,
1
,
43
,
43
,
43
,
43
,
44
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
44
,
43
,
43
,
45
,
43
,
43
,
43
,
43
,
45
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
0
,
43
,
43
}
;
static
yyconst
flex_int16_t
yy_nxt
[
72
]
=
static
yyconst
flex_int16_t
yy_nxt
[
91
]
=
{
0
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
4
,
11
,
4
,
4
,
4
,
4
,
4
,
4
,
4
,
12
,
4
,
4
,
13
,
4
,
4
,
31
,
17
,
34
,
32
,
33
,
31
,
30
,
29
,
28
,
27
,
26
,
25
,
24
,
23
,
22
,
21
,
16
,
15
,
14
,
20
,
19
,
18
,
16
,
15
,
14
,
35
,
3
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
4
,
4
,
15
,
16
,
17
,
4
,
4
,
4
,
4
,
4
,
18
,
4
,
4
,
19
,
4
,
4
,
24
,
24
,
24
,
24
,
24
,
24
,
25
,
24
,
24
,
22
,
30
,
22
,
42
,
41
,
40
,
39
,
38
,
37
,
36
,
35
,
34
,
33
,
32
,
31
,
23
,
21
,
20
,
29
,
28
,
27
,
26
,
23
,
21
,
20
,
43
,
3
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
}
;
static
yyconst
flex_int16_t
yy_chk
[
72
]
=
static
yyconst
flex_int16_t
yy_chk
[
91
]
=
{
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
31
,
36
,
32
,
30
,
31
,
29
,
28
,
27
,
26
,
25
,
24
,
23
,
22
,
21
,
20
,
19
,
17
,
15
,
14
,
13
,
12
,
11
,
7
,
6
,
5
,
3
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
,
35
1
,
1
,
1
,
1
,
1
,
1
,
1
,
11
,
11
,
12
,
12
,
13
,
13
,
12
,
24
,
24
,
44
,
45
,
44
,
41
,
40
,
39
,
37
,
36
,
35
,
34
,
33
,
32
,
29
,
28
,
27
,
22
,
21
,
20
,
19
,
18
,
17
,
14
,
7
,
6
,
5
,
3
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
,
43
}
;
/* Table of booleans, true if rule could match eol. */
static
yyconst
flex_int32_t
yy_rule_can_match_eol
[
1
2
]
=
static
yyconst
flex_int32_t
yy_rule_can_match_eol
[
1
7
]
=
{
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
};
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
};
static
yy_state_type
yy_last_accepting_state
;
static
char
*
yy_last_accepting_cpos
;
...
...
@@ -567,9 +581,10 @@ static char *yy_last_accepting_cpos;
extern
int
yy_flex_debug
;
int
yy_flex_debug
=
1
;
static
yyconst
flex_int16_t
yy_rule_linenum
[
1
1
]
=
static
yyconst
flex_int16_t
yy_rule_linenum
[
1
6
]
=
{
0
,
83
,
87
,
93
,
103
,
154
,
155
,
156
,
157
,
158
,
160
83
,
87
,
93
,
103
,
109
,
123
,
124
,
125
,
126
,
127
,
128
,
129
,
130
,
131
,
133
}
;
/* The intent behind this definition is that it'll catch
...
...
@@ -636,7 +651,7 @@ static isc::eval::location loc;
// by moving it ahead by yyleng bytes. yyleng specifies the length of the
// currently matched token.
#define YY_USER_ACTION loc.columns(yyleng);
#line 6
40
"lexer.cc"
#line 6
55
"lexer.cc"
#define INITIAL 0
...
...
@@ -875,17 +890,6 @@ YY_DECL
register
char
*
yy_cp
,
*
yy_bp
;
register
int
yy_act
;
/* %% [7.0] user's declarations go here */
#line 76 "lexer.ll"
// Code run each time yylex is called.
loc
.
step
();
#line 888 "lexer.cc"
if
(
!
(
yy_init
)
)
{
(
yy_init
)
=
1
;
...
...
@@ -920,6 +924,18 @@ YY_DECL
yy_load_buffer_state
(
);
}
{
/* %% [7.0] user's declarations go here */
#line 76 "lexer.ll"
// Code run each time yylex is called.
loc
.
step
();
#line 938 "lexer.cc"
while
(
1
)
/* loops until end-of-file is reached */
{
/* %% [8.0] yymore()-related code goes here */
...
...
@@ -938,7 +954,7 @@ YY_DECL
yy_match:
do
{
register
YY_CHAR
yy_c
=
yy_ec
[
YY_SC_TO_UI
(
*
yy_cp
)];
register
YY_CHAR
yy_c
=
yy_ec
[
YY_SC_TO_UI
(
*
yy_cp
)]
;
if
(
yy_accept
[
yy_current_state
]
)
{
(
yy_last_accepting_state
)
=
yy_current_state
;
...
...
@@ -947,13 +963,13 @@ yy_match:
while
(
yy_chk
[
yy_base
[
yy_current_state
]
+
yy_c
]
!=
yy_current_state
)
{
yy_current_state
=
(
int
)
yy_def
[
yy_current_state
];
if
(
yy_current_state
>=
36
)
if
(
yy_current_state
>=
44
)
yy_c
=
yy_meta
[(
unsigned
int
)
yy_c
];
}
yy_current_state
=
yy_nxt
[
yy_base
[
yy_current_state
]
+
(
unsigned
int
)
yy_c
];
++
yy_cp
;
}
while
(
yy_current_state
!=
3
5
);
while
(
yy_current_state
!=
4
3
);
yy_cp
=
(
yy_last_accepting_cpos
);
yy_current_state
=
(
yy_last_accepting_state
);
...
...
@@ -967,7 +983,7 @@ yy_find_action:
if
(
yy_act
!=
YY_END_OF_BUFFER
&&
yy_rule_can_match_eol
[
yy_act
]
)
{
in
t
yyl
;
yy_size_
t
yyl
;
for
(
yyl
=
0
;
yyl
<
yyleng
;
++
yyl
)
if
(
yytext
[
yyl
]
==
'\n'
)
...
...
@@ -982,13 +998,13 @@ do_action: /* This label is used only to access EOF actions. */
{
if
(
yy_act
==
0
)
fprintf
(
stderr
,
"--scanner backing up
\n
"
);
else
if
(
yy_act
<
1
1
)
else
if
(
yy_act
<
1
6
)
fprintf
(
stderr
,
"--accepting rule at line %ld (
\"
%s
\"
)
\n
"
,
(
long
)
yy_rule_linenum
[
yy_act
],
yytext
);
else
if
(
yy_act
==
1
1
)
else
if
(
yy_act
==
1
6
)
fprintf
(
stderr
,
"--accepting default rule (
\"
%s
\"
)
\n
"
,
yytext
);
else
if
(
yy_act
==
1
2
)
else
if
(
yy_act
==
1
7
)
fprintf
(
stderr
,
"--(end of buffer or a NUL)
\n
"
);
else
fprintf
(
stderr
,
"--EOF (start condition %d)
\n
"
,
YY_START
);
...
...
@@ -1039,96 +1055,88 @@ case 4:
YY_RULE_SETUP
#line 103 "lexer.ll"
{
// option[123] token found. Let's see if the numeric value can be
// converted to integer and if it has a reasonable value.
// yytext contains the whole expression (.e.g. option[123]). We need
// to trim it down to just the code, which will be transformed to
// integer.
// A hex string has been matched. It contains the '0x' or '0X' header
// followed by at least one hexadecimal digit.
return
isc
::
eval
::
EvalParser
::
make_HEXSTRING
(
yytext
,
loc
);
}
YY_BREAK
case
5
:
YY_RULE_SETUP
#line 109 "lexer.ll"
{
// An integer was found.
std
::
string
tmp
(
yytext
);
// Sanity check if the token is at least 9 (strlen("option[X]")) long.
// This should never happen as it would indicate bison bug.
if
(
tmp
.
length
()
<
9
)
{
driver
.
error
(
loc
,
"The string matched ("
+
tmp
+
") is too short,"
" expected at least 9 (option[X]) characters"
);
}
size_t
pos
=
tmp
.
find
(
"["
);
if
(
pos
==
std
::
string
::
npos
)
{
driver
.
error
(
loc
,
"The string matched ("
+
tmp
+
") is invalid,"
" as it does not contain opening bracket."
);
}
// Let's get rid of all the text before [, including [.
tmp
=
tmp
.
substr
(
pos
+
1
);
// And finally remove the trailing ].
pos
=
tmp
.
find
(
"]"
);
if
(
pos
==
std
::
string
::
npos
)
{
driver
.
error
(
loc
,
"The string matched ("
+
tmp
+
") is invalid,"
" as it does not contain closing bracket."
);
}
tmp
=
tmp
.
substr
(
0
,
pos
);
uint16_t
n
=
0
;
try
{
n
=
boost
::
lexical_cast
<
int
>
(
tmp
);
static_cast
<
void
>
(
boost
::
lexical_cast
<
int
>
(
tmp
)
)
;
}
catch
(
const
boost
::
bad_lexical_cast
&
)
{
driver
.
error
(
loc
,
"Failed to convert specified option code to "
"number ('"
+
tmp
+
"' in expression "
+
std
::
string
(
yytext
));
}
// 65535 is the maximum value of the option code in DHCPv6. We want the
// code to be the same for v4 and v6, so let's ignore for a moment that
// max. option code in DHCPv4 is 255.
/// @todo: Maybe add a flag somewhere in EvalContext to indicate if we're
/// running in v4 (allowed max 255) or v6 (allowed max 65535).
if
(
n
<
0
||
n
>
65535
)
{
driver
.
error
(
loc
,
"Option code has invalid value in "
+
std
::
string
(
yytext
)
+
". Allowed range: 0..65535"
);
driver
.
error
(
loc
,
"Failed to convert "
+
tmp
+
" to an integer."
);
}
return
isc
::
eval
::
EvalParser
::
make_OPTION
(
n
,
loc
);
// The parser needs the string form as double conversion is no lossless
return
isc
::
eval
::
EvalParser
::
make_INTEGER
(
tmp
,
loc
);
}
YY_BREAK
case
5
:
<