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
ISC Open Source Projects
Kea
Commits
fd12a6d6
Commit
fd12a6d6
authored
Nov 23, 2015
by
Francis Dupont
Browse files
[4097a] Merged #4093
parent
09df1b38
Changes
21
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
fd12a6d6
1052. [func] marcin
libeval: expressions involving options can now use textual or
hexadecimal format of the options.
(Trac #4093 git 4cdf0fff1067b3dde6570dc6831e8b1343bc50fe)
1051. [func] [tmark]
kea-dhcp4 and kea-dhcp6 configuration parsing now supports
the "client-classes" element for defining client classes.
...
...
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
fd12a6d6
...
...
@@ -1696,7 +1696,7 @@ TEST_F(Dhcpv4SrvTest, matchClassification) {
"
\"
option-data
\"
: ["
" {
\"
name
\"
:
\"
ip-forwarding
\"
, "
"
\"
data
\"
:
\"
true
\"
} ], "
"
\"
test
\"
:
\"
option[12] == 'foo'
\"
} ] }"
;
"
\"
test
\"
:
\"
option[12]
.text
== 'foo'
\"
} ] }"
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
ConstElementPtr
status
;
...
...
@@ -1792,7 +1792,7 @@ TEST_F(Dhcpv4SrvTest, subnetClassPriority) {
"
\"
option-data
\"
: ["
" {
\"
name
\"
:
\"
ip-forwarding
\"
, "
"
\"
data
\"
:
\"
true
\"
} ], "
"
\"
test
\"
:
\"
option[12] == 'foo'
\"
} ] }"
;
"
\"
test
\"
:
\"
option[12]
.text
== 'foo'
\"
} ] }"
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
ConstElementPtr
status
;
...
...
@@ -1869,7 +1869,7 @@ TEST_F(Dhcpv4SrvTest, classGlobalPriority) {
"
\"
option-data
\"
: ["
" {
\"
name
\"
:
\"
ip-forwarding
\"
, "
"
\"
data
\"
:
\"
true
\"
} ], "
"
\"
test
\"
:
\"
option[12] == 'foo'
\"
} ] }"
;
"
\"
test
\"
:
\"
option[12]
.text
== 'foo'
\"
} ] }"
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
ConstElementPtr
status
;
...
...
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
fd12a6d6
...
...
@@ -1866,7 +1866,7 @@ TEST_F(Dhcpv6SrvTest, matchClassification) {
"
\"
option-data
\"
: ["
" {
\"
name
\"
:
\"
ipv6-forwarding
\"
, "
"
\"
data
\"
:
\"
true
\"
} ], "
"
\"
test
\"
:
\"
option[1234] == 'foo'
\"
} ] }"
;
"
\"
test
\"
:
\"
option[1234]
.text
== 'foo'
\"
} ] }"
;
ASSERT_NO_THROW
(
configure
(
config
));
// Create packets with enough to select the subnet
...
...
@@ -1962,7 +1962,7 @@ TEST_F(Dhcpv6SrvTest, subnetClassPriority) {
"
\"
option-data
\"
: ["
" {
\"
name
\"
:
\"
ipv6-forwarding
\"
, "
"
\"
data
\"
:
\"
true
\"
} ], "
"
\"
test
\"
:
\"
option[1234] == 'foo'
\"
} ] }"
;
"
\"
test
\"
:
\"
option[1234]
.text
== 'foo'
\"
} ] }"
;
ASSERT_NO_THROW
(
configure
(
config
));
// Create a packet with enough to select the subnet and go through
...
...
@@ -2037,7 +2037,7 @@ TEST_F(Dhcpv6SrvTest, classGlobalPriority) {
"
\"
option-data
\"
: ["
" {
\"
name
\"
:
\"
ipv6-forwarding
\"
, "
"
\"
data
\"
:
\"
true
\"
} ], "
"
\"
test
\"
:
\"
option[1234] == 'foo'
\"
} ] }"
;
"
\"
test
\"
:
\"
option[1234]
.text
== 'foo'
\"
} ] }"
;
ASSERT_NO_THROW
(
configure
(
config
));
// Create a packet with enough to select the subnet and go through
...
...
src/lib/dhcp/option.cc
View file @
fd12a6d6
...
...
@@ -16,6 +16,7 @@
#include
<dhcp/libdhcp++.h>
#include
<dhcp/option.h>
#include
<exceptions/exceptions.h>
#include
<util/encode/hex.h>
#include
<util/io_utilities.h>
#include
<iomanip>
...
...
@@ -219,6 +220,34 @@ Option::toString() {
return
(
toText
(
0
));
}
std
::
string
Option
::
toHexString
(
const
bool
include_header
)
{
OutputBuffer
buf
(
len
());
try
{
// If the option is too long, exception will be thrown. We allow
// for this exception to propagate to not mask this error.
pack
(
buf
);
}
catch
(
const
std
::
exception
&
ex
)
{
isc_throw
(
OutOfRange
,
"unable to obtain hexadecimal representation"
" of option "
<<
getType
()
<<
": "
<<
ex
.
what
());
}
const
uint8_t
*
option_data
=
static_cast
<
const
uint8_t
*>
(
buf
.
getData
());
std
::
vector
<
uint8_t
>
option_vec
;
// Assign option data to a vector, with or without option header depending
// on the value of "include_header" flag.
option_vec
.
assign
(
option_data
+
(
include_header
?
0
:
getHeaderLen
()),
option_data
+
buf
.
getLength
());
// Return hexadecimal representation prepended with 0x or empty string
// if option has no payload and the header fields are excluded.
std
::
ostringstream
s
;
if
(
!
option_vec
.
empty
())
{
s
<<
"0x"
<<
encode
::
encodeHex
(
option_vec
);
}
return
(
s
.
str
());
}
std
::
string
Option
::
headerToText
(
const
int
indent
,
const
std
::
string
&
type_name
)
{
...
...
src/lib/dhcp/option.h
View file @
fd12a6d6
...
...
@@ -216,6 +216,15 @@ public:
/// @return string that represents the value of the option.
virtual
std
::
string
toString
();
/// @brief Returns string containing hexadecimal representation of option.
///
/// @param include_header Boolean flag which indicates if the output should
/// also contain header fields. The default is that it shouldn't include
/// header fields.
///
/// @return String containing hexadecimal representation of the option.
virtual
std
::
string
toHexString
(
const
bool
include_header
=
false
);
/// Returns option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
///
/// @return option type
...
...
src/lib/dhcp/tests/option_unittest.cc
View file @
fd12a6d6
...
...
@@ -236,6 +236,38 @@ TEST_F(OptionTest, v4_toText) {
EXPECT_EQ
(
"type=253, len=003: 00:0f:ff"
,
opt
.
toText
());
}
// Test converting option to the hexadecimal representation.
TEST_F
(
OptionTest
,
v4_toHexString
)
{
std
::
vector
<
uint8_t
>
payload
;
for
(
unsigned
int
i
=
0
;
i
<
16
;
++
i
)
{
payload
.
push_back
(
static_cast
<
uint8_t
>
(
i
));
}
Option
opt
(
Option
::
V4
,
122
,
payload
);
EXPECT_EQ
(
"0x000102030405060708090A0B0C0D0E0F"
,
opt
.
toHexString
());
EXPECT_EQ
(
"0x7A10000102030405060708090A0B0C0D0E0F"
,
opt
.
toHexString
(
true
));
// Test empty option.
Option
opt_empty
(
Option
::
V4
,
65
,
std
::
vector
<
uint8_t
>
());
EXPECT_TRUE
(
opt_empty
.
toHexString
().
empty
());
EXPECT_EQ
(
"0x4100"
,
opt_empty
.
toHexString
(
true
));
// Test too long option. We can't simply create such option by
// providing a long payload, because class constructor would not
// accept it. Instead we'll add two long sub options after we
// create an option instance.
Option
opt_too_long
(
Option
::
V4
,
33
);
// Both suboptions have payloads of 150 bytes.
std
::
vector
<
uint8_t
>
long_payload
(
150
,
1
);
OptionPtr
sub1
(
new
Option
(
Option
::
V4
,
100
,
long_payload
));
OptionPtr
sub2
(
new
Option
(
Option
::
V4
,
101
,
long_payload
));
opt_too_long
.
addOption
(
sub1
);
opt_too_long
.
addOption
(
sub2
);
// The toHexString() should throw exception.
EXPECT_THROW
(
opt_too_long
.
toHexString
(),
isc
::
OutOfRange
);
}
// Tests simple constructor
TEST_F
(
OptionTest
,
v6_basic
)
{
...
...
@@ -446,6 +478,22 @@ TEST_F(OptionTest, v6_toText) {
EXPECT_EQ
(
"type=00258, len=00003: 00:0f:ff"
,
opt
->
toText
());
}
// Test converting option to the hexadecimal representation.
TEST_F
(
OptionTest
,
v6_toHexString
)
{
std
::
vector
<
uint8_t
>
payload
;
for
(
unsigned
int
i
=
0
;
i
<
16
;
++
i
)
{
payload
.
push_back
(
static_cast
<
uint8_t
>
(
i
));
}
Option
opt
(
Option
::
V6
,
12202
,
payload
);
EXPECT_EQ
(
"0x000102030405060708090A0B0C0D0E0F"
,
opt
.
toHexString
());
EXPECT_EQ
(
"0x2FAA0010000102030405060708090A0B0C0D0E0F"
,
opt
.
toHexString
(
true
));
// Test empty option.
Option
opt_empty
(
Option
::
V6
,
65000
,
std
::
vector
<
uint8_t
>
());
EXPECT_TRUE
(
opt_empty
.
toHexString
().
empty
());
EXPECT_EQ
(
"0xFDE80000"
,
opt_empty
.
toHexString
(
true
));
}
TEST_F
(
OptionTest
,
getUintX
)
{
...
...
src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc
View file @
fd12a6d6
...
...
@@ -119,7 +119,7 @@ TEST(ExpressionParserTest, validExpression4) {
ExpressionPtr
parsed_expr
;
// Turn config into elements. This may emit exceptions.
std
::
string
cfg_txt
=
"
\"
option[100] == 'hundred4'
\"
"
;
std
::
string
cfg_txt
=
"
\"
option[100]
.text
== 'hundred4'
\"
"
;
ElementPtr
config_element
=
Element
::
fromJSON
(
cfg_txt
);
// Create the parser.
...
...
@@ -150,7 +150,7 @@ TEST(ExpressionParserTest, validExpression6) {
ExpressionPtr
parsed_expr
;
// Turn config into elements. This may emit exceptions.
std
::
string
cfg_txt
=
"
\"
option[100] == 'hundred6'
\"
"
;
std
::
string
cfg_txt
=
"
\"
option[100]
.text
== 'hundred6'
\"
"
;
ElementPtr
config_element
=
Element
::
fromJSON
(
cfg_txt
);
// Create the parser.
...
...
@@ -249,7 +249,7 @@ TEST_F(ClientClassDefParserTest, nameAndExpressionClass) {
std
::
string
cfg_text
=
"{
\n
"
"
\"
name
\"
:
\"
class_one
\"
,
\n
"
"
\"
test
\"
:
\"
option[100] == 'works right'
\"
\n
"
"
\"
test
\"
:
\"
option[100]
.text
== 'works right'
\"
\n
"
"}
\n
"
;
ClientClassDefPtr
cclass
;
...
...
@@ -325,7 +325,7 @@ TEST_F(ClientClassDefParserTest, basicValidClass) {
std
::
string
cfg_text
=
"{
\n
"
"
\"
name
\"
:
\"
MICROSOFT
\"
,
\n
"
"
\"
test
\"
:
\"
option[100] == 'booya'
\"
,
\n
"
"
\"
test
\"
:
\"
option[100]
.text
== 'booya'
\"
,
\n
"
"
\"
option-data
\"
: [
\n
"
" {
\n
"
"
\"
name
\"
:
\"
domain-name-servers
\"
,
\n
"
...
...
@@ -368,7 +368,7 @@ TEST_F(ClientClassDefParserTest, noClassName) {
std
::
string
cfg_text
=
"{
\n
"
"
\"
test
\"
:
\"
option[123] == 'abc'
\"
,
\n
"
"
\"
test
\"
:
\"
option[123]
.text
== 'abc'
\"
,
\n
"
"
\"
option-data
\"
: [
\n
"
" {
\n
"
"
\"
name
\"
:
\"
domain-name-servers
\"
,
\n
"
...
...
@@ -391,7 +391,7 @@ TEST_F(ClientClassDefParserTest, blankClassName) {
std
::
string
cfg_text
=
"{
\n
"
"
\"
name
\"
:
\"\"
,
\n
"
"
\"
test
\"
:
\"
option[123] == 'abc'
\"
,
\n
"
"
\"
test
\"
:
\"
option[123]
.text
== 'abc'
\"
,
\n
"
"
\"
option-data
\"
: [
\n
"
" {
\n
"
"
\"
name
\"
:
\"
domain-name-servers
\"
,
\n
"
...
...
src/lib/eval/eval.dox
View file @
fd12a6d6
...
...
@@ -18,8 +18,9 @@
@section dhcpEvalIntroduction Introduction
The core of the libeval library is a parser that is able to parse an
expression (e.g. option[123] == 'APC'). This is currently used for client
classification, but in the future may be also used for other applications.
expression (e.g. option[123].text == 'APC'). This is currently used for
client 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 a major method:
...
...
@@ -79,12 +80,17 @@
14. TokenPtr hex(new TokenHexString($1));
15. ctx.expression.push_back(hex);
16. }
17. | OPTION '[' INTEGER ']'
17. | OPTION '[' INTEGER ']'
DOT TEXT
18. {
19. TokenPtr opt(new TokenOption($3));
19. TokenPtr opt(new TokenOption($3
, TokenOption::TEXTUAL
));
20. ctx.expression.push_back(opt);
21. }
22. ;
21. }
22. | OPTION '[' INTEGER ']' DOT HEX
23. {
24. TokenPtr opt(new TokenOption($3, TokenOption::HEXADECIMAL));
25. ctx.expression.push_back(opt);
26. }
27. ;
@endcode
This code determines that the grammar starts from expression (line 1).
...
...
@@ -92,7 +98,8 @@ 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-22: it may either be a string (lines 7-11),
a hex string (lines 12-16) or option (lines 17-21).
a hex string (lines 12-16), option in the textual format (lines 17-21)
or option in a hexadecimal format (lines 22-26).
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/lexer.cc
View file @
fd12a6d6
...
...
@@ -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
9
#define YY_FLEX_SUBMINOR_VERSION 3
5
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
...
...
@@ -72,6 +72,7 @@ typedef int16_t flex_int16_t;
typedef
uint16_t
flex_uint16_t
;
typedef
int32_t
flex_int32_t
;
typedef
uint32_t
flex_uint32_t
;
typedef
uint64_t
flex_uint64_t
;
#else
typedef
signed
char
flex_int8_t
;
typedef
short
int
flex_int16_t
;
...
...
@@ -79,6 +80,7 @@ typedef int flex_int32_t;
typedef
unsigned
char
flex_uint8_t
;
typedef
unsigned
short
int
flex_uint16_t
;
typedef
unsigned
int
flex_uint32_t
;
#endif
/* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
...
...
@@ -109,8 +111,6 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
#endif
/* ! C99 */
#endif
/* ! FLEXINT_H */
/* %endif */
...
...
@@ -225,18 +225,11 @@ extern FILE *yyin, *yyout;
*/
#define YY_LESS_LINENO(n) \
do { \
in
t yyl;\
yy_size_
t yyl;\
for ( yyl = n; yyl < yyleng; ++yyl )\
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) \
...
...
@@ -427,7 +420,7 @@ void yyfree (void * );
/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
/* Begin user sect3 */
#define yywrap() 1
#define yywrap(
n
) 1
#define YY_SKIP_YYWRAP
#define FLEX_DEBUG
...
...
@@ -445,8 +438,6 @@ 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
);
...
...
@@ -462,15 +453,15 @@ static void yy_fatal_error (yyconst char msg[] );
#define YY_DO_BEFORE_ACTION \
(yytext_ptr) = yy_bp; \
/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */
\
yyleng = (size_t) (yy_cp - yy_bp); \
yyleng = (
yy_
size_t) (yy_cp - yy_bp); \
(yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */
\
(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
6
#define YY_END_OF_BUFFER
17
#define YY_NUM_RULES 1
9
#define YY_END_OF_BUFFER
20
/* This struct is not used in this scanner,
but its presence is necessary. */
struct
yy_trans_info
...
...
@@ -478,13 +469,14 @@ struct yy_trans_info
flex_int32_t
yy_verify
;
flex_int32_t
yy_nxt
;
};
static
yyconst
flex_int16_t
yy_accept
[
44
]
=
static
yyconst
flex_int16_t
yy_accept
[
52
]
=
{
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
0
,
0
,
20
,
18
,
1
,
2
,
18
,
13
,
14
,
17
,
18
,
12
,
5
,
5
,
18
,
15
,
16
,
18
,
18
,
18
,
18
,
18
,
1
,
2
,
0
,
3
,
5
,
0
,
6
,
0
,
0
,
0
,
0
,
0
,
4
,
11
,
9
,
0
,
0
,
0
,
0
,
0
,
8
,
0
,
0
,
7
,
0
,
0
,
0
,
10
,
0
}
;
static
yyconst
flex_int32_t
yy_ec
[
256
]
=
...
...
@@ -493,15 +485,15 @@ 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
,
8
,
1
,
1
,
9
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
1
0
,
1
,
1
,
1
,
1
1
,
1
,
1
,
1
,
1
2
,
1
2
,
1
2
,
1
2
,
1
2
,
1
2
,
6
,
1
,
1
,
7
,
8
,
9
,
1
,
10
,
1
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
3
,
1
3
,
1
3
,
1
3
,
1
3
,
1
3
,
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
,
1
,
1
,
1
,
1
,
1
,
1
,
1
4
,
1
,
1
,
1
5
,
1
,
1
6
,
1
,
1
,
1
,
1
7
,
1
8
,
1
3
,
1
3
,
1
2
,
1
2
,
18
,
1
,
19
,
1
,
1
,
2
0
,
1
,
2
1
,
2
2
,
2
3
,
1
,
2
4
,
2
5
,
2
6
,
27
,
1
,
1
,
1
3
,
1
9
,
1
3
,
20
,
2
1
,
22
,
1
,
1
,
2
3
,
1
,
2
4
,
2
5
,
2
6
,
1
,
2
7
,
2
8
,
2
9
,
30
,
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
,
...
...
@@ -519,61 +511,71 @@ static yyconst flex_int32_t yy_ec[256] =
1
,
1
,
1
,
1
,
1
}
;
static
yyconst
flex_int32_t
yy_meta
[
2
8
]
=
static
yyconst
flex_int32_t
yy_meta
[
3
2
]
=
{
0
,
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
1
,
1
,
2
,
1
,
1
,
1
,
1
,
1
,
1
,
3
,
3
,
1
,
3
,
1
,
1
,
1
,
3
,
3
,
3
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
}
;
static
yyconst
flex_int16_t
yy_base
[
4
6
]
=
static
yyconst
flex_int16_t
yy_base
[
5
4
]
=
{
0
,
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
0
,
0
,
72
,
73
,
69
,
67
,
65
,
73
,
73
,
73
,
22
,
73
,
24
,
26
,
56
,
73
,
73
,
44
,
47
,
39
,
34
,
44
,
60
,
58
,
56
,
73
,
29
,
0
,
73
,
36
,
26
,
25
,
35
,
21
,
0
,
73
,
73
,
29
,
22
,
20
,
23
,
18
,
73
,
22
,
18
,
73
,
22
,
19
,
22
,
73
,
73
,
55
,
38
}
;
static
yyconst
flex_int16_t
yy_def
[
4
6
]
=
static
yyconst
flex_int16_t
yy_def
[
5
4
]
=
{
0
,
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
51
,
1
,
51
,
51
,
51
,
51
,
52
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
52
,
51
,
51
,
53
,
51
,
51
,
51
,
51
,
51
,
51
,
53
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
0
,
51
,
51
}
;
static
yyconst
flex_int16_t
yy_nxt
[
9
1
]
=
static
yyconst
flex_int16_t
yy_nxt
[
1
05
]
=
{
0
,
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
14
,
15
,
4
,
4
,
16
,
17
,
18
,
4
,
4
,
4
,
19
,
4
,
4
,
4
,
20
,
4
,
4
,
21
,
22
,
4
,
4
,
27
,
27
,
27
,
27
,
27
,
27
,
28
,
27
,
27
,
35
,
50
,
49
,
48
,
47
,
46
,
45
,
44
,
43
,
42
,
41
,
40
,
39
,
38
,
28
,
25
,
37
,
25
,
36
,
26
,
24
,
23
,
34
,
33
,
32
,
31
,
30
,
29
,
26
,
24
,
23
,
51
,
3
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
}
;
static
yyconst
flex_int16_t
yy_chk
[
9
1
]
=
static
yyconst
flex_int16_t
yy_chk
[
1
05
]
=
{
0
,
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
,
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
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
11
,
11
,
13
,
13
,
14
,
14
,
13
,
27
,
27
,
53
,
49
,
48
,
47
,
45
,
44
,
42
,
41
,
40
,
39
,
38
,
34
,
33
,
32
,
13
,
52
,
31
,
52
,
30
,
25
,
24
,
23
,
22
,
21
,
20
,
19
,
18
,
15
,
7
,
6
,
5
,
3
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
,
51
}
;
/* Table of booleans, true if rule could match eol. */
static
yyconst
flex_int32_t
yy_rule_can_match_eol
[
17
]
=
static
yyconst
flex_int32_t
yy_rule_can_match_eol
[
20
]
=
{
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
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
,
0
,
0
,
0
,
};
static
yy_state_type
yy_last_accepting_state
;
static
char
*
yy_last_accepting_cpos
;
...
...
@@ -581,10 +583,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
6
]
=
static
yyconst
flex_int16_t
yy_rule_linenum
[
1
9
]
=
{
0
,
83
,
87
,
93
,
103
,
109
,
123
,
124
,
125
,
126
,
127
,
128
,
129
,
130
,
131
,
13
3
128
,
129
,
130
,
131
,
13
2
,
133
,
134
,
136
}
;
/* The intent behind this definition is that it'll catch
...
...
@@ -651,7 +653,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 65
5
"lexer.cc"
#line 65
7
"lexer.cc"
#define INITIAL 0
...
...
@@ -769,7 +771,7 @@ static int input (void );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
#define ECHO
do { if (
fwrite( yytext, yyleng, 1, yyout )
) {} } while (0)
#define ECHO fwrite( yytext, yyleng, 1, yyout )
/* %endif */
/* %if-c++-only C++ definition */
/* %endif */
...
...
@@ -784,7 +786,7 @@ static int input (void );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
size_t n; \
yy_
size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
...
...
@@ -890,6 +892,17 @@ 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 905 "lexer.cc"
if
(
!
(
yy_init
)
)
{
(
yy_init
)
=
1
;
...
...
@@ -924,18 +937,6 @@ 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 */
...
...
@@ -954,7 +955,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
)];