162ac0c33Sjakob %{
262ac0c33Sjakob /*
362ac0c33Sjakob * zlexer.lex - lexical analyzer for (DNS) zone files
462ac0c33Sjakob *
5d3fecca9Ssthen * Copyright (c) 2001-2006, NLnet Labs. All rights reserved
662ac0c33Sjakob *
762ac0c33Sjakob * See LICENSE for the license.
862ac0c33Sjakob *
962ac0c33Sjakob */
108d298c9fSsthen /* because flex keeps having sign-unsigned compare problems that are unfixed*/
118d298c9fSsthen #if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2))))
128d298c9fSsthen #pragma GCC diagnostic ignored "-Wsign-compare"
138d298c9fSsthen #endif
148d298c9fSsthen /* ignore fallthrough warnings in the generated parse code case statements */
158d298c9fSsthen #if defined(__clang__)||(defined(__GNUC__)&&(__GNUC__ >=7))
168d298c9fSsthen #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
178d298c9fSsthen #endif
1862ac0c33Sjakob
19aee1b7aaSsthen #include "config.h"
2062ac0c33Sjakob
2162ac0c33Sjakob #include <ctype.h>
2262ac0c33Sjakob #include <errno.h>
2362ac0c33Sjakob #include <string.h>
2462ac0c33Sjakob #include <strings.h>
2562ac0c33Sjakob
2662ac0c33Sjakob #include "zonec.h"
2762ac0c33Sjakob #include "dname.h"
2862ac0c33Sjakob #include "zparser.h"
2962ac0c33Sjakob
3062ac0c33Sjakob #if 0
3162ac0c33Sjakob #define LEXOUT(s) printf s /* used ONLY when debugging */
3262ac0c33Sjakob #else
3362ac0c33Sjakob #define LEXOUT(s)
3462ac0c33Sjakob #endif
3562ac0c33Sjakob
3662ac0c33Sjakob enum lexer_state {
3762ac0c33Sjakob EXPECT_OWNER,
3862ac0c33Sjakob PARSING_OWNER,
3962ac0c33Sjakob PARSING_TTL_CLASS_TYPE,
4062ac0c33Sjakob PARSING_RDATA
4162ac0c33Sjakob };
4262ac0c33Sjakob
4362ac0c33Sjakob static int parse_token(int token, char *yytext, enum lexer_state *lexer_state);
4462ac0c33Sjakob
4562ac0c33Sjakob static YY_BUFFER_STATE include_stack[MAXINCLUDES];
4662ac0c33Sjakob static zparser_type zparser_stack[MAXINCLUDES];
4762ac0c33Sjakob static int include_stack_ptr = 0;
4862ac0c33Sjakob
4962ac0c33Sjakob /*
5062ac0c33Sjakob * Saves the file specific variables on the include stack.
5162ac0c33Sjakob */
5262ac0c33Sjakob static void
push_parser_state(FILE * input)5362ac0c33Sjakob push_parser_state(FILE *input)
5462ac0c33Sjakob {
5562ac0c33Sjakob zparser_stack[include_stack_ptr].filename = parser->filename;
5662ac0c33Sjakob zparser_stack[include_stack_ptr].line = parser->line;
5762ac0c33Sjakob zparser_stack[include_stack_ptr].origin = parser->origin;
5862ac0c33Sjakob include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
5962ac0c33Sjakob yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
6062ac0c33Sjakob ++include_stack_ptr;
6162ac0c33Sjakob }
6262ac0c33Sjakob
6362ac0c33Sjakob /*
6462ac0c33Sjakob * Restores the file specific variables from the include stack.
6562ac0c33Sjakob */
6662ac0c33Sjakob static void
pop_parser_state(void)6762ac0c33Sjakob pop_parser_state(void)
6862ac0c33Sjakob {
69eab1363eSsthen if (parser->filename)
70eab1363eSsthen region_recycle(parser->region, (void *)parser->filename,
71eab1363eSsthen strlen(parser->filename)+1);
72eab1363eSsthen
7362ac0c33Sjakob --include_stack_ptr;
7462ac0c33Sjakob parser->filename = zparser_stack[include_stack_ptr].filename;
7562ac0c33Sjakob parser->line = zparser_stack[include_stack_ptr].line;
7662ac0c33Sjakob parser->origin = zparser_stack[include_stack_ptr].origin;
7762ac0c33Sjakob yy_delete_buffer(YY_CURRENT_BUFFER);
7862ac0c33Sjakob yy_switch_to_buffer(include_stack[include_stack_ptr]);
7962ac0c33Sjakob }
8062ac0c33Sjakob
81d3fecca9Ssthen static YY_BUFFER_STATE oldstate;
82d3fecca9Ssthen /* Start string scan */
83d3fecca9Ssthen void
parser_push_stringbuf(char * str)84d3fecca9Ssthen parser_push_stringbuf(char* str)
85d3fecca9Ssthen {
86d3fecca9Ssthen oldstate = YY_CURRENT_BUFFER;
87d3fecca9Ssthen yy_switch_to_buffer(yy_scan_string(str));
88d3fecca9Ssthen }
89d3fecca9Ssthen
90d3fecca9Ssthen void
parser_pop_stringbuf(void)91d3fecca9Ssthen parser_pop_stringbuf(void)
92d3fecca9Ssthen {
93d3fecca9Ssthen yy_delete_buffer(YY_CURRENT_BUFFER);
94d3fecca9Ssthen yy_switch_to_buffer(oldstate);
95d3fecca9Ssthen oldstate = NULL;
96d3fecca9Ssthen }
97d3fecca9Ssthen
98ee5153b7Sflorian static int paren_open = 0;
99ee5153b7Sflorian static enum lexer_state lexer_state = EXPECT_OWNER;
100ee5153b7Sflorian void
parser_flush(void)101ee5153b7Sflorian parser_flush(void)
102ee5153b7Sflorian {
103ee5153b7Sflorian YY_FLUSH_BUFFER;
104ee5153b7Sflorian paren_open = 0;
105ee5153b7Sflorian lexer_state = EXPECT_OWNER;
106ee5153b7Sflorian }
107ee5153b7Sflorian
at_eof(void)108*de04d855Ssthen int at_eof(void)
109*de04d855Ssthen {
110*de04d855Ssthen static int once = 1;
111*de04d855Ssthen return (once = !once) ? 0 : NL;
112*de04d855Ssthen }
113*de04d855Ssthen
11462ac0c33Sjakob #ifndef yy_set_bol /* compat definition, for flex 2.4.6 */
11562ac0c33Sjakob #define yy_set_bol(at_bol) \
11662ac0c33Sjakob { \
11762ac0c33Sjakob if ( ! yy_current_buffer ) \
11862ac0c33Sjakob yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
11962ac0c33Sjakob yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \
12062ac0c33Sjakob }
12162ac0c33Sjakob #endif
12262ac0c33Sjakob
12362ac0c33Sjakob %}
124d3fecca9Ssthen %option noinput
125d3fecca9Ssthen %option nounput
126d3fecca9Ssthen %{
127d3fecca9Ssthen #ifndef YY_NO_UNPUT
128d3fecca9Ssthen #define YY_NO_UNPUT 1
129d3fecca9Ssthen #endif
130d3fecca9Ssthen #ifndef YY_NO_INPUT
131d3fecca9Ssthen #define YY_NO_INPUT 1
132d3fecca9Ssthen #endif
133d3fecca9Ssthen %}
13462ac0c33Sjakob
13562ac0c33Sjakob SPACE [ \t]
13662ac0c33Sjakob LETTER [a-zA-Z]
13762ac0c33Sjakob NEWLINE [\n\r]
13815ed76cbSbrad ZONESTR [^ \t\n\r();.\"\$]|\\.|\\\n
1398d298c9fSsthen CHARSTR [^ \t\n\r();.\"]|\\.|\\\n
14015ed76cbSbrad QUOTE \"
14162ac0c33Sjakob DOLLAR \$
14262ac0c33Sjakob COMMENT ;
14362ac0c33Sjakob DOT \.
14462ac0c33Sjakob BIT [^\]\n]|\\.
14562ac0c33Sjakob ANY [^\"\n\\]|\\.
14662ac0c33Sjakob
14762ac0c33Sjakob %x incl bitlabel quotedstring
14862ac0c33Sjakob
14962ac0c33Sjakob %%
15062ac0c33Sjakob {SPACE}*{COMMENT}.* /* ignore */
15162ac0c33Sjakob ^{DOLLAR}TTL { lexer_state = PARSING_RDATA; return DOLLAR_TTL; }
15262ac0c33Sjakob ^{DOLLAR}ORIGIN { lexer_state = PARSING_RDATA; return DOLLAR_ORIGIN; }
15362ac0c33Sjakob
15462ac0c33Sjakob /*
15562ac0c33Sjakob * Handle $INCLUDE directives. See
15662ac0c33Sjakob * http://dinosaur.compilertools.net/flex/flex_12.html#SEC12.
15762ac0c33Sjakob */
15862ac0c33Sjakob ^{DOLLAR}INCLUDE {
15962ac0c33Sjakob BEGIN(incl);
1608d298c9fSsthen /* ignore case statement fallthrough on incl<EOF> flex rule */
16162ac0c33Sjakob }
16262ac0c33Sjakob <incl>\n |
16362ac0c33Sjakob <incl><<EOF>> {
16462ac0c33Sjakob int error_occurred = parser->error_occurred;
16562ac0c33Sjakob BEGIN(INITIAL);
16662ac0c33Sjakob zc_error("missing file name in $INCLUDE directive");
16762ac0c33Sjakob yy_set_bol(1); /* Set beginning of line, so "^" rules match. */
16862ac0c33Sjakob ++parser->line;
16962ac0c33Sjakob parser->error_occurred = error_occurred;
17062ac0c33Sjakob }
17162ac0c33Sjakob <incl>.+ {
17262ac0c33Sjakob char *tmp;
17362ac0c33Sjakob domain_type *origin = parser->origin;
17462ac0c33Sjakob int error_occurred = parser->error_occurred;
17562ac0c33Sjakob
17662ac0c33Sjakob BEGIN(INITIAL);
17762ac0c33Sjakob if (include_stack_ptr >= MAXINCLUDES ) {
17862ac0c33Sjakob zc_error("includes nested too deeply, skipped (>%d)",
17962ac0c33Sjakob MAXINCLUDES);
18062ac0c33Sjakob } else {
18162ac0c33Sjakob FILE *input;
18262ac0c33Sjakob
18362ac0c33Sjakob /* Remove trailing comment. */
18462ac0c33Sjakob tmp = strrchr(yytext, ';');
18562ac0c33Sjakob if (tmp) {
18662ac0c33Sjakob *tmp = '\0';
18762ac0c33Sjakob }
18862ac0c33Sjakob strip_string(yytext);
18962ac0c33Sjakob
19062ac0c33Sjakob /* Parse origin for include file. */
19162ac0c33Sjakob tmp = strrchr(yytext, ' ');
19262ac0c33Sjakob if (!tmp) {
19362ac0c33Sjakob tmp = strrchr(yytext, '\t');
19462ac0c33Sjakob }
19562ac0c33Sjakob if (tmp) {
19662ac0c33Sjakob const dname_type *dname;
19762ac0c33Sjakob
19862ac0c33Sjakob /* split the original yytext */
19962ac0c33Sjakob *tmp = '\0';
20062ac0c33Sjakob strip_string(yytext);
20162ac0c33Sjakob
20262ac0c33Sjakob dname = dname_parse(parser->region, tmp + 1);
20362ac0c33Sjakob if (!dname) {
20462ac0c33Sjakob zc_error("incorrect include origin '%s'",
20562ac0c33Sjakob tmp + 1);
2060c2b6c02Sjakob } else if (*(tmp + strlen(tmp + 1)) != '.') {
2070c2b6c02Sjakob zc_error("$INCLUDE directive requires absolute domain name");
20862ac0c33Sjakob } else {
20962ac0c33Sjakob origin = domain_table_insert(
21062ac0c33Sjakob parser->db->domains, dname);
21162ac0c33Sjakob }
21262ac0c33Sjakob }
21362ac0c33Sjakob
21462ac0c33Sjakob if (strlen(yytext) == 0) {
21562ac0c33Sjakob zc_error("missing file name in $INCLUDE directive");
21662ac0c33Sjakob } else if (!(input = fopen(yytext, "r"))) {
21762ac0c33Sjakob zc_error("cannot open include file '%s': %s",
21862ac0c33Sjakob yytext, strerror(errno));
21962ac0c33Sjakob } else {
22062ac0c33Sjakob /* Initialize parser for include file. */
22162ac0c33Sjakob char *filename = region_strdup(parser->region, yytext);
22262ac0c33Sjakob push_parser_state(input); /* Destroys yytext. */
22362ac0c33Sjakob parser->filename = filename;
22462ac0c33Sjakob parser->line = 1;
22562ac0c33Sjakob parser->origin = origin;
22662ac0c33Sjakob lexer_state = EXPECT_OWNER;
22762ac0c33Sjakob }
22862ac0c33Sjakob }
22962ac0c33Sjakob
23062ac0c33Sjakob parser->error_occurred = error_occurred;
23162ac0c33Sjakob }
23262ac0c33Sjakob <INITIAL><<EOF>> {
233*de04d855Ssthen int eo = at_eof();
23462ac0c33Sjakob yy_set_bol(1); /* Set beginning of line, so "^" rules match. */
23562ac0c33Sjakob if (include_stack_ptr == 0) {
236*de04d855Ssthen if(eo == NL)
237*de04d855Ssthen return eo;
23862ac0c33Sjakob yyterminate();
23962ac0c33Sjakob } else {
24062ac0c33Sjakob fclose(yyin);
24162ac0c33Sjakob pop_parser_state();
242*de04d855Ssthen if(eo == NL)
243*de04d855Ssthen return eo;
24462ac0c33Sjakob }
24562ac0c33Sjakob }
24662ac0c33Sjakob ^{DOLLAR}{LETTER}+ { zc_warning("Unknown directive: %s", yytext); }
24762ac0c33Sjakob {DOT} {
24862ac0c33Sjakob LEXOUT((". "));
24962ac0c33Sjakob return parse_token('.', yytext, &lexer_state);
25062ac0c33Sjakob }
25162ac0c33Sjakob @ {
25262ac0c33Sjakob LEXOUT(("@ "));
25362ac0c33Sjakob return parse_token('@', yytext, &lexer_state);
25462ac0c33Sjakob }
25562ac0c33Sjakob \\# {
25662ac0c33Sjakob LEXOUT(("\\# "));
25762ac0c33Sjakob return parse_token(URR, yytext, &lexer_state);
25862ac0c33Sjakob }
25962ac0c33Sjakob {NEWLINE} {
26062ac0c33Sjakob ++parser->line;
26162ac0c33Sjakob if (!paren_open) {
26262ac0c33Sjakob lexer_state = EXPECT_OWNER;
26362ac0c33Sjakob LEXOUT(("NL\n"));
26462ac0c33Sjakob return NL;
26562ac0c33Sjakob } else {
26662ac0c33Sjakob LEXOUT(("SP "));
26762ac0c33Sjakob return SP;
26862ac0c33Sjakob }
26962ac0c33Sjakob }
27062ac0c33Sjakob \( {
27162ac0c33Sjakob if (paren_open) {
27262ac0c33Sjakob zc_error("nested parentheses");
27362ac0c33Sjakob yyterminate();
27462ac0c33Sjakob }
27562ac0c33Sjakob LEXOUT(("( "));
27662ac0c33Sjakob paren_open = 1;
27762ac0c33Sjakob return SP;
27862ac0c33Sjakob }
27962ac0c33Sjakob \) {
28062ac0c33Sjakob if (!paren_open) {
28162ac0c33Sjakob zc_error("closing parentheses without opening parentheses");
28262ac0c33Sjakob yyterminate();
28362ac0c33Sjakob }
28462ac0c33Sjakob LEXOUT((") "));
28562ac0c33Sjakob paren_open = 0;
28662ac0c33Sjakob return SP;
28762ac0c33Sjakob }
28862ac0c33Sjakob {SPACE}+ {
28962ac0c33Sjakob if (!paren_open && lexer_state == EXPECT_OWNER) {
29062ac0c33Sjakob lexer_state = PARSING_TTL_CLASS_TYPE;
29162ac0c33Sjakob LEXOUT(("PREV "));
29262ac0c33Sjakob return PREV;
29362ac0c33Sjakob }
29462ac0c33Sjakob if (lexer_state == PARSING_OWNER) {
29562ac0c33Sjakob lexer_state = PARSING_TTL_CLASS_TYPE;
29662ac0c33Sjakob }
29762ac0c33Sjakob LEXOUT(("SP "));
29862ac0c33Sjakob return SP;
29962ac0c33Sjakob }
30062ac0c33Sjakob
30162ac0c33Sjakob /* Bitlabels. Strip leading and ending brackets. */
30262ac0c33Sjakob \\\[ { BEGIN(bitlabel); }
30362ac0c33Sjakob <bitlabel><<EOF>> {
30462ac0c33Sjakob zc_error("EOF inside bitlabel");
30562ac0c33Sjakob BEGIN(INITIAL);
306d3fecca9Ssthen yyrestart(yyin); /* this is so that lex does not give an internal err */
307d3fecca9Ssthen yyterminate();
30862ac0c33Sjakob }
30962ac0c33Sjakob <bitlabel>{BIT}* { yymore(); }
31062ac0c33Sjakob <bitlabel>\n { ++parser->line; yymore(); }
31162ac0c33Sjakob <bitlabel>\] {
31262ac0c33Sjakob BEGIN(INITIAL);
31362ac0c33Sjakob yytext[yyleng - 1] = '\0';
31462ac0c33Sjakob return parse_token(BITLAB, yytext, &lexer_state);
31562ac0c33Sjakob }
31662ac0c33Sjakob
31762ac0c33Sjakob /* Quoted strings. Strip leading and ending quotes. */
31815ed76cbSbrad {QUOTE} { BEGIN(quotedstring); LEXOUT(("\" ")); }
31962ac0c33Sjakob <quotedstring><<EOF>> {
32062ac0c33Sjakob zc_error("EOF inside quoted string");
32162ac0c33Sjakob BEGIN(INITIAL);
322d3fecca9Ssthen yyrestart(yyin); /* this is so that lex does not give an internal err */
323d3fecca9Ssthen yyterminate();
32462ac0c33Sjakob }
3258d298c9fSsthen <quotedstring>{ANY}* { LEXOUT(("QSTR ")); yymore(); }
32662ac0c33Sjakob <quotedstring>\n { ++parser->line; yymore(); }
32715ed76cbSbrad <quotedstring>{QUOTE} {
32862ac0c33Sjakob LEXOUT(("\" "));
32962ac0c33Sjakob BEGIN(INITIAL);
33062ac0c33Sjakob yytext[yyleng - 1] = '\0';
3318d298c9fSsthen return parse_token(QSTR, yytext, &lexer_state);
33262ac0c33Sjakob }
33362ac0c33Sjakob
33415ed76cbSbrad {ZONESTR}({CHARSTR})* {
33562ac0c33Sjakob /* Any allowed word. */
33662ac0c33Sjakob return parse_token(STR, yytext, &lexer_state);
33762ac0c33Sjakob }
33862ac0c33Sjakob . {
33962ac0c33Sjakob zc_error("unknown character '%c' (\\%03d) seen - is this a zonefile?",
34062ac0c33Sjakob (int) yytext[0], (int) yytext[0]);
34162ac0c33Sjakob }
34262ac0c33Sjakob %%
34362ac0c33Sjakob
34462ac0c33Sjakob /*
34562ac0c33Sjakob * Analyze "word" to see if it matches an RR type, possibly by using
34662ac0c33Sjakob * the "TYPExxx" notation. If it matches, the corresponding token is
34762ac0c33Sjakob * returned and the TYPE parameter is set to the RR type value.
34862ac0c33Sjakob */
34962ac0c33Sjakob static int
35062ac0c33Sjakob rrtype_to_token(const char *word, uint16_t *type)
35162ac0c33Sjakob {
35262ac0c33Sjakob uint16_t t = rrtype_from_string(word);
35362ac0c33Sjakob if (t != 0) {
35462ac0c33Sjakob rrtype_descriptor_type *entry = rrtype_descriptor_by_type(t);
35562ac0c33Sjakob *type = t;
35662ac0c33Sjakob return entry->token;
35762ac0c33Sjakob }
35862ac0c33Sjakob
35962ac0c33Sjakob return 0;
36062ac0c33Sjakob }
36162ac0c33Sjakob
36262ac0c33Sjakob
36362ac0c33Sjakob /*
36462ac0c33Sjakob * Remove \DDD constructs from the input. See RFC 1035, section 5.1.
36562ac0c33Sjakob */
36662ac0c33Sjakob static size_t
36762ac0c33Sjakob zoctet(char *text)
36862ac0c33Sjakob {
36962ac0c33Sjakob /*
37062ac0c33Sjakob * s follows the string, p lags behind and rebuilds the new
37162ac0c33Sjakob * string
37262ac0c33Sjakob */
37362ac0c33Sjakob char *s;
37462ac0c33Sjakob char *p;
37562ac0c33Sjakob
37662ac0c33Sjakob for (s = p = text; *s; ++s, ++p) {
37762ac0c33Sjakob assert(p <= s);
37862ac0c33Sjakob if (s[0] != '\\') {
37962ac0c33Sjakob /* Ordinary character. */
38062ac0c33Sjakob *p = *s;
38182cafdebSmillert } else if (isdigit((unsigned char)s[1]) && isdigit((unsigned char)s[2]) && isdigit((unsigned char)s[3])) {
38262ac0c33Sjakob /* \DDD escape. */
38362ac0c33Sjakob int val = (hexdigit_to_int(s[1]) * 100 +
38462ac0c33Sjakob hexdigit_to_int(s[2]) * 10 +
38562ac0c33Sjakob hexdigit_to_int(s[3]));
38662ac0c33Sjakob if (0 <= val && val <= 255) {
38762ac0c33Sjakob s += 3;
38862ac0c33Sjakob *p = val;
38962ac0c33Sjakob } else {
39062ac0c33Sjakob zc_warning("text escape \\DDD overflow");
39162ac0c33Sjakob *p = *++s;
39262ac0c33Sjakob }
39362ac0c33Sjakob } else if (s[1] != '\0') {
39462ac0c33Sjakob /* \X where X is any character, keep X. */
39562ac0c33Sjakob *p = *++s;
39662ac0c33Sjakob } else {
39762ac0c33Sjakob /* Trailing backslash, ignore it. */
39862ac0c33Sjakob zc_warning("trailing backslash ignored");
39962ac0c33Sjakob --p;
40062ac0c33Sjakob }
40162ac0c33Sjakob }
40262ac0c33Sjakob *p = '\0';
40362ac0c33Sjakob return p - text;
40462ac0c33Sjakob }
40562ac0c33Sjakob
40662ac0c33Sjakob static int
40762ac0c33Sjakob parse_token(int token, char *yytext, enum lexer_state *lexer_state)
40862ac0c33Sjakob {
409a8b34139Sjakob size_t len;
410a8b34139Sjakob char *str;
41162ac0c33Sjakob
41262ac0c33Sjakob if (*lexer_state == EXPECT_OWNER) {
41362ac0c33Sjakob *lexer_state = PARSING_OWNER;
41462ac0c33Sjakob } else if (*lexer_state == PARSING_TTL_CLASS_TYPE) {
41562ac0c33Sjakob const char *t;
41662ac0c33Sjakob int token;
41762ac0c33Sjakob uint16_t rrclass;
41862ac0c33Sjakob
41962ac0c33Sjakob /* type */
420a8b34139Sjakob token = rrtype_to_token(yytext, &yylval.type);
42162ac0c33Sjakob if (token != 0) {
42262ac0c33Sjakob *lexer_state = PARSING_RDATA;
42362ac0c33Sjakob LEXOUT(("%d[%s] ", token, yytext));
42462ac0c33Sjakob return token;
42562ac0c33Sjakob }
42662ac0c33Sjakob
42762ac0c33Sjakob /* class */
428a8b34139Sjakob rrclass = rrclass_from_string(yytext);
42962ac0c33Sjakob if (rrclass != 0) {
43062ac0c33Sjakob yylval.klass = rrclass;
43162ac0c33Sjakob LEXOUT(("CLASS "));
43262ac0c33Sjakob return T_RRCLASS;
43362ac0c33Sjakob }
43462ac0c33Sjakob
43562ac0c33Sjakob /* ttl */
436a8b34139Sjakob yylval.ttl = strtottl(yytext, &t);
43762ac0c33Sjakob if (*t == '\0') {
43862ac0c33Sjakob LEXOUT(("TTL "));
43962ac0c33Sjakob return T_TTL;
44062ac0c33Sjakob }
44162ac0c33Sjakob }
44262ac0c33Sjakob
443a8b34139Sjakob str = region_strdup(parser->rr_region, yytext);
444a8b34139Sjakob len = zoctet(str);
445a8b34139Sjakob
44662ac0c33Sjakob yylval.data.str = str;
44762ac0c33Sjakob yylval.data.len = len;
44862ac0c33Sjakob
44962ac0c33Sjakob LEXOUT(("%d[%s] ", token, yytext));
45062ac0c33Sjakob return token;
45162ac0c33Sjakob }
452